// Copyright (c) Lawrence Livermore National Security, LLC and other VisIt
// Project developers.  See the top-level LICENSE file for dates and other
// details.  No copyright assignment is required to contribute to VisIt.

#include <avtDatabaseMetaData.h>
#include <DataNode.h>
#include <avtExpressionTypeConversions.h>
#include <ImproperUseException.h>
#include <InvalidVariableException.h>
#include <BadIndexException.h>
#include <DebugStream.h>
#include <ParsingExprList.h>
#include <ExprNode.h>
#include <plugin_vartypes.h>
#include <avtMeshMetaData.h>
#include <avtSubsetsMetaData.h>
#include <avtScalarMetaData.h>
#include <avtVectorMetaData.h>
#include <avtTensorMetaData.h>
#include <avtSymmetricTensorMetaData.h>
#include <avtArrayMetaData.h>
#include <avtMaterialMetaData.h>
#include <avtSpeciesMetaData.h>
#include <avtCurveMetaData.h>
#include <avtLabelMetaData.h>
#include <avtDefaultPlotMetaData.h>

// ****************************************************************************
// Method: avtDatabaseMetaData::avtDatabaseMetaData
//
// Purpose:
//   Init utility for the avtDatabaseMetaData class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

void avtDatabaseMetaData::Init()
{
    hasTemporalExtents = false;
    minTemporalExtents = 0;
    maxTemporalExtents = 0;
    numStates = 0;
    isVirtualDatabase = false;
    mustRepopulateOnStateChange = false;
    mustAlphabetizeVariables = true;
    formatCanDoDomainDecomposition = false;
    formatCanDoMultires = false;
    useCatchAllMesh = false;
    isSimulation = false;
    replacementMask = -65;

    avtDatabaseMetaData::SelectAll();
}

// ****************************************************************************
// Method: avtDatabaseMetaData::avtDatabaseMetaData
//
// Purpose:
//   Copy utility for the avtDatabaseMetaData class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

void avtDatabaseMetaData::Copy(const avtDatabaseMetaData &obj)
{
    AttributeGroupVector::const_iterator pos;

    hasTemporalExtents = obj.hasTemporalExtents;
    minTemporalExtents = obj.minTemporalExtents;
    maxTemporalExtents = obj.maxTemporalExtents;
    numStates = obj.numStates;
    isVirtualDatabase = obj.isVirtualDatabase;
    mustRepopulateOnStateChange = obj.mustRepopulateOnStateChange;
    mustAlphabetizeVariables = obj.mustAlphabetizeVariables;
    formatCanDoDomainDecomposition = obj.formatCanDoDomainDecomposition;
    formatCanDoMultires = obj.formatCanDoMultires;
    useCatchAllMesh = obj.useCatchAllMesh;
    timeStepPath = obj.timeStepPath;
    timeStepNames = obj.timeStepNames;
    cycles = obj.cycles;
    cyclesAreAccurate = obj.cyclesAreAccurate;
    times = obj.times;
    timesAreAccurate = obj.timesAreAccurate;
    databaseName = obj.databaseName;
    fileFormat = obj.fileFormat;
    databaseComment = obj.databaseComment;
    exprList = obj.exprList;
    // *** Copy the meshes field ***
    // Delete the AttributeGroup objects and clear the vector.
    for(pos = meshes.begin(); pos != meshes.end(); ++pos)
        delete *pos;
    meshes.clear();
    if(obj.meshes.size() > 0)
        meshes.reserve(obj.meshes.size());
    // Duplicate the meshes from obj.
    for(pos = obj.meshes.begin(); pos != obj.meshes.end(); ++pos)
    {
        avtMeshMetaData *oldavtMeshMetaData = (avtMeshMetaData *)(*pos);
        avtMeshMetaData *newavtMeshMetaData = new avtMeshMetaData(*oldavtMeshMetaData);
        meshes.push_back(newavtMeshMetaData);
    }

    // *** Copy the subsets field ***
    // Delete the AttributeGroup objects and clear the vector.
    for(pos = subsets.begin(); pos != subsets.end(); ++pos)
        delete *pos;
    subsets.clear();
    if(obj.subsets.size() > 0)
        subsets.reserve(obj.subsets.size());
    // Duplicate the subsets from obj.
    for(pos = obj.subsets.begin(); pos != obj.subsets.end(); ++pos)
    {
        avtSubsetsMetaData *oldavtSubsetsMetaData = (avtSubsetsMetaData *)(*pos);
        avtSubsetsMetaData *newavtSubsetsMetaData = new avtSubsetsMetaData(*oldavtSubsetsMetaData);
        subsets.push_back(newavtSubsetsMetaData);
    }

    // *** Copy the scalars field ***
    // Delete the AttributeGroup objects and clear the vector.
    for(pos = scalars.begin(); pos != scalars.end(); ++pos)
        delete *pos;
    scalars.clear();
    if(obj.scalars.size() > 0)
        scalars.reserve(obj.scalars.size());
    // Duplicate the scalars from obj.
    for(pos = obj.scalars.begin(); pos != obj.scalars.end(); ++pos)
    {
        avtScalarMetaData *oldavtScalarMetaData = (avtScalarMetaData *)(*pos);
        avtScalarMetaData *newavtScalarMetaData = new avtScalarMetaData(*oldavtScalarMetaData);
        scalars.push_back(newavtScalarMetaData);
    }

    // *** Copy the vectors field ***
    // Delete the AttributeGroup objects and clear the vector.
    for(pos = vectors.begin(); pos != vectors.end(); ++pos)
        delete *pos;
    vectors.clear();
    if(obj.vectors.size() > 0)
        vectors.reserve(obj.vectors.size());
    // Duplicate the vectors from obj.
    for(pos = obj.vectors.begin(); pos != obj.vectors.end(); ++pos)
    {
        avtVectorMetaData *oldavtVectorMetaData = (avtVectorMetaData *)(*pos);
        avtVectorMetaData *newavtVectorMetaData = new avtVectorMetaData(*oldavtVectorMetaData);
        vectors.push_back(newavtVectorMetaData);
    }

    // *** Copy the tensors field ***
    // Delete the AttributeGroup objects and clear the vector.
    for(pos = tensors.begin(); pos != tensors.end(); ++pos)
        delete *pos;
    tensors.clear();
    if(obj.tensors.size() > 0)
        tensors.reserve(obj.tensors.size());
    // Duplicate the tensors from obj.
    for(pos = obj.tensors.begin(); pos != obj.tensors.end(); ++pos)
    {
        avtTensorMetaData *oldavtTensorMetaData = (avtTensorMetaData *)(*pos);
        avtTensorMetaData *newavtTensorMetaData = new avtTensorMetaData(*oldavtTensorMetaData);
        tensors.push_back(newavtTensorMetaData);
    }

    // *** Copy the symmTensors field ***
    // Delete the AttributeGroup objects and clear the vector.
    for(pos = symmTensors.begin(); pos != symmTensors.end(); ++pos)
        delete *pos;
    symmTensors.clear();
    if(obj.symmTensors.size() > 0)
        symmTensors.reserve(obj.symmTensors.size());
    // Duplicate the symmTensors from obj.
    for(pos = obj.symmTensors.begin(); pos != obj.symmTensors.end(); ++pos)
    {
        avtSymmetricTensorMetaData *oldavtSymmetricTensorMetaData = (avtSymmetricTensorMetaData *)(*pos);
        avtSymmetricTensorMetaData *newavtSymmetricTensorMetaData = new avtSymmetricTensorMetaData(*oldavtSymmetricTensorMetaData);
        symmTensors.push_back(newavtSymmetricTensorMetaData);
    }

    // *** Copy the arrays field ***
    // Delete the AttributeGroup objects and clear the vector.
    for(pos = arrays.begin(); pos != arrays.end(); ++pos)
        delete *pos;
    arrays.clear();
    if(obj.arrays.size() > 0)
        arrays.reserve(obj.arrays.size());
    // Duplicate the arrays from obj.
    for(pos = obj.arrays.begin(); pos != obj.arrays.end(); ++pos)
    {
        avtArrayMetaData *oldavtArrayMetaData = (avtArrayMetaData *)(*pos);
        avtArrayMetaData *newavtArrayMetaData = new avtArrayMetaData(*oldavtArrayMetaData);
        arrays.push_back(newavtArrayMetaData);
    }

    // *** Copy the materials field ***
    // Delete the AttributeGroup objects and clear the vector.
    for(pos = materials.begin(); pos != materials.end(); ++pos)
        delete *pos;
    materials.clear();
    if(obj.materials.size() > 0)
        materials.reserve(obj.materials.size());
    // Duplicate the materials from obj.
    for(pos = obj.materials.begin(); pos != obj.materials.end(); ++pos)
    {
        avtMaterialMetaData *oldavtMaterialMetaData = (avtMaterialMetaData *)(*pos);
        avtMaterialMetaData *newavtMaterialMetaData = new avtMaterialMetaData(*oldavtMaterialMetaData);
        materials.push_back(newavtMaterialMetaData);
    }

    // *** Copy the species field ***
    // Delete the AttributeGroup objects and clear the vector.
    for(pos = species.begin(); pos != species.end(); ++pos)
        delete *pos;
    species.clear();
    if(obj.species.size() > 0)
        species.reserve(obj.species.size());
    // Duplicate the species from obj.
    for(pos = obj.species.begin(); pos != obj.species.end(); ++pos)
    {
        avtSpeciesMetaData *oldavtSpeciesMetaData = (avtSpeciesMetaData *)(*pos);
        avtSpeciesMetaData *newavtSpeciesMetaData = new avtSpeciesMetaData(*oldavtSpeciesMetaData);
        species.push_back(newavtSpeciesMetaData);
    }

    // *** Copy the curves field ***
    // Delete the AttributeGroup objects and clear the vector.
    for(pos = curves.begin(); pos != curves.end(); ++pos)
        delete *pos;
    curves.clear();
    if(obj.curves.size() > 0)
        curves.reserve(obj.curves.size());
    // Duplicate the curves from obj.
    for(pos = obj.curves.begin(); pos != obj.curves.end(); ++pos)
    {
        avtCurveMetaData *oldavtCurveMetaData = (avtCurveMetaData *)(*pos);
        avtCurveMetaData *newavtCurveMetaData = new avtCurveMetaData(*oldavtCurveMetaData);
        curves.push_back(newavtCurveMetaData);
    }

    // *** Copy the labels field ***
    // Delete the AttributeGroup objects and clear the vector.
    for(pos = labels.begin(); pos != labels.end(); ++pos)
        delete *pos;
    labels.clear();
    if(obj.labels.size() > 0)
        labels.reserve(obj.labels.size());
    // Duplicate the labels from obj.
    for(pos = obj.labels.begin(); pos != obj.labels.end(); ++pos)
    {
        avtLabelMetaData *oldavtLabelMetaData = (avtLabelMetaData *)(*pos);
        avtLabelMetaData *newavtLabelMetaData = new avtLabelMetaData(*oldavtLabelMetaData);
        labels.push_back(newavtLabelMetaData);
    }

    // *** Copy the defaultPlots field ***
    // Delete the AttributeGroup objects and clear the vector.
    for(pos = defaultPlots.begin(); pos != defaultPlots.end(); ++pos)
        delete *pos;
    defaultPlots.clear();
    if(obj.defaultPlots.size() > 0)
        defaultPlots.reserve(obj.defaultPlots.size());
    // Duplicate the defaultPlots from obj.
    for(pos = obj.defaultPlots.begin(); pos != obj.defaultPlots.end(); ++pos)
    {
        avtDefaultPlotMetaData *oldavtDefaultPlotMetaData = (avtDefaultPlotMetaData *)(*pos);
        avtDefaultPlotMetaData *newavtDefaultPlotMetaData = new avtDefaultPlotMetaData(*oldavtDefaultPlotMetaData);
        defaultPlots.push_back(newavtDefaultPlotMetaData);
    }

    isSimulation = obj.isSimulation;
    simInfo = obj.simInfo;
    suggestedDefaultSILRestriction = obj.suggestedDefaultSILRestriction;
    replacementMask = obj.replacementMask;

    avtDatabaseMetaData::SelectAll();
}

// Type map format string
const char *avtDatabaseMetaData::TypeMapFormatString = AVTDATABASEMETADATA_TMFS;
const AttributeGroup::private_tmfs_t avtDatabaseMetaData::TmfsStruct = {AVTDATABASEMETADATA_TMFS};


// ****************************************************************************
// Method: avtDatabaseMetaData::avtDatabaseMetaData
//
// Purpose:
//   Default constructor for the avtDatabaseMetaData class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

avtDatabaseMetaData::avtDatabaseMetaData() :
    AttributeSubject(avtDatabaseMetaData::TypeMapFormatString)
{
    avtDatabaseMetaData::Init();
}

// ****************************************************************************
// Method: avtDatabaseMetaData::avtDatabaseMetaData
//
// Purpose:
//   Constructor for the derived classes of avtDatabaseMetaData class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

avtDatabaseMetaData::avtDatabaseMetaData(private_tmfs_t tmfs) :
    AttributeSubject(tmfs.tmfs)
{
    avtDatabaseMetaData::Init();
}

// ****************************************************************************
// Method: avtDatabaseMetaData::avtDatabaseMetaData
//
// Purpose:
//   Copy constructor for the avtDatabaseMetaData class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

avtDatabaseMetaData::avtDatabaseMetaData(const avtDatabaseMetaData &obj) :
    AttributeSubject(avtDatabaseMetaData::TypeMapFormatString)
{
    avtDatabaseMetaData::Copy(obj);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::avtDatabaseMetaData
//
// Purpose:
//   Copy constructor for derived classes of the avtDatabaseMetaData class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

avtDatabaseMetaData::avtDatabaseMetaData(const avtDatabaseMetaData &obj, private_tmfs_t tmfs) :
    AttributeSubject(tmfs.tmfs)
{
    avtDatabaseMetaData::Copy(obj);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::~avtDatabaseMetaData
//
// Purpose:
//   Destructor for the avtDatabaseMetaData class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

avtDatabaseMetaData::~avtDatabaseMetaData()
{
    AttributeGroupVector::iterator pos;

    // Destroy the meshes field.
    for(pos = meshes.begin(); pos != meshes.end(); ++pos)
        delete *pos;
    // Destroy the subsets field.
    for(pos = subsets.begin(); pos != subsets.end(); ++pos)
        delete *pos;
    // Destroy the scalars field.
    for(pos = scalars.begin(); pos != scalars.end(); ++pos)
        delete *pos;
    // Destroy the vectors field.
    for(pos = vectors.begin(); pos != vectors.end(); ++pos)
        delete *pos;
    // Destroy the tensors field.
    for(pos = tensors.begin(); pos != tensors.end(); ++pos)
        delete *pos;
    // Destroy the symmTensors field.
    for(pos = symmTensors.begin(); pos != symmTensors.end(); ++pos)
        delete *pos;
    // Destroy the arrays field.
    for(pos = arrays.begin(); pos != arrays.end(); ++pos)
        delete *pos;
    // Destroy the materials field.
    for(pos = materials.begin(); pos != materials.end(); ++pos)
        delete *pos;
    // Destroy the species field.
    for(pos = species.begin(); pos != species.end(); ++pos)
        delete *pos;
    // Destroy the curves field.
    for(pos = curves.begin(); pos != curves.end(); ++pos)
        delete *pos;
    // Destroy the labels field.
    for(pos = labels.begin(); pos != labels.end(); ++pos)
        delete *pos;
    // Destroy the defaultPlots field.
    for(pos = defaultPlots.begin(); pos != defaultPlots.end(); ++pos)
        delete *pos;
}

// ****************************************************************************
// Method: avtDatabaseMetaData::operator =
//
// Purpose:
//   Assignment operator for the avtDatabaseMetaData class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

avtDatabaseMetaData&
avtDatabaseMetaData::operator = (const avtDatabaseMetaData &obj)
{
    if (this == &obj) return *this;

    avtDatabaseMetaData::Copy(obj);

    return *this;
}

// ****************************************************************************
// Method: avtDatabaseMetaData::operator ==
//
// Purpose:
//   Comparison operator == for the avtDatabaseMetaData class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

bool
avtDatabaseMetaData::operator == (const avtDatabaseMetaData &obj) const
{
    bool meshes_equal = (obj.meshes.size() == meshes.size());
    for(size_t i = 0; (i < meshes.size()) && meshes_equal; ++i)
    {
        // Make references to avtMeshMetaData from AttributeGroup *.
        const avtMeshMetaData &meshes1 = *((const avtMeshMetaData *)(meshes[i]));
        const avtMeshMetaData &meshes2 = *((const avtMeshMetaData *)(obj.meshes[i]));
        meshes_equal = (meshes1 == meshes2);
    }

    bool subsets_equal = (obj.subsets.size() == subsets.size());
    for(size_t i = 0; (i < subsets.size()) && subsets_equal; ++i)
    {
        // Make references to avtSubsetsMetaData from AttributeGroup *.
        const avtSubsetsMetaData &subsets1 = *((const avtSubsetsMetaData *)(subsets[i]));
        const avtSubsetsMetaData &subsets2 = *((const avtSubsetsMetaData *)(obj.subsets[i]));
        subsets_equal = (subsets1 == subsets2);
    }

    bool scalars_equal = (obj.scalars.size() == scalars.size());
    for(size_t i = 0; (i < scalars.size()) && scalars_equal; ++i)
    {
        // Make references to avtScalarMetaData from AttributeGroup *.
        const avtScalarMetaData &scalars1 = *((const avtScalarMetaData *)(scalars[i]));
        const avtScalarMetaData &scalars2 = *((const avtScalarMetaData *)(obj.scalars[i]));
        scalars_equal = (scalars1 == scalars2);
    }

    bool vectors_equal = (obj.vectors.size() == vectors.size());
    for(size_t i = 0; (i < vectors.size()) && vectors_equal; ++i)
    {
        // Make references to avtVectorMetaData from AttributeGroup *.
        const avtVectorMetaData &vectors1 = *((const avtVectorMetaData *)(vectors[i]));
        const avtVectorMetaData &vectors2 = *((const avtVectorMetaData *)(obj.vectors[i]));
        vectors_equal = (vectors1 == vectors2);
    }

    bool tensors_equal = (obj.tensors.size() == tensors.size());
    for(size_t i = 0; (i < tensors.size()) && tensors_equal; ++i)
    {
        // Make references to avtTensorMetaData from AttributeGroup *.
        const avtTensorMetaData &tensors1 = *((const avtTensorMetaData *)(tensors[i]));
        const avtTensorMetaData &tensors2 = *((const avtTensorMetaData *)(obj.tensors[i]));
        tensors_equal = (tensors1 == tensors2);
    }

    bool symmTensors_equal = (obj.symmTensors.size() == symmTensors.size());
    for(size_t i = 0; (i < symmTensors.size()) && symmTensors_equal; ++i)
    {
        // Make references to avtSymmetricTensorMetaData from AttributeGroup *.
        const avtSymmetricTensorMetaData &symmTensors1 = *((const avtSymmetricTensorMetaData *)(symmTensors[i]));
        const avtSymmetricTensorMetaData &symmTensors2 = *((const avtSymmetricTensorMetaData *)(obj.symmTensors[i]));
        symmTensors_equal = (symmTensors1 == symmTensors2);
    }

    bool arrays_equal = (obj.arrays.size() == arrays.size());
    for(size_t i = 0; (i < arrays.size()) && arrays_equal; ++i)
    {
        // Make references to avtArrayMetaData from AttributeGroup *.
        const avtArrayMetaData &arrays1 = *((const avtArrayMetaData *)(arrays[i]));
        const avtArrayMetaData &arrays2 = *((const avtArrayMetaData *)(obj.arrays[i]));
        arrays_equal = (arrays1 == arrays2);
    }

    bool materials_equal = (obj.materials.size() == materials.size());
    for(size_t i = 0; (i < materials.size()) && materials_equal; ++i)
    {
        // Make references to avtMaterialMetaData from AttributeGroup *.
        const avtMaterialMetaData &materials1 = *((const avtMaterialMetaData *)(materials[i]));
        const avtMaterialMetaData &materials2 = *((const avtMaterialMetaData *)(obj.materials[i]));
        materials_equal = (materials1 == materials2);
    }

    bool species_equal = (obj.species.size() == species.size());
    for(size_t i = 0; (i < species.size()) && species_equal; ++i)
    {
        // Make references to avtSpeciesMetaData from AttributeGroup *.
        const avtSpeciesMetaData &species1 = *((const avtSpeciesMetaData *)(species[i]));
        const avtSpeciesMetaData &species2 = *((const avtSpeciesMetaData *)(obj.species[i]));
        species_equal = (species1 == species2);
    }

    bool curves_equal = (obj.curves.size() == curves.size());
    for(size_t i = 0; (i < curves.size()) && curves_equal; ++i)
    {
        // Make references to avtCurveMetaData from AttributeGroup *.
        const avtCurveMetaData &curves1 = *((const avtCurveMetaData *)(curves[i]));
        const avtCurveMetaData &curves2 = *((const avtCurveMetaData *)(obj.curves[i]));
        curves_equal = (curves1 == curves2);
    }

    bool labels_equal = (obj.labels.size() == labels.size());
    for(size_t i = 0; (i < labels.size()) && labels_equal; ++i)
    {
        // Make references to avtLabelMetaData from AttributeGroup *.
        const avtLabelMetaData &labels1 = *((const avtLabelMetaData *)(labels[i]));
        const avtLabelMetaData &labels2 = *((const avtLabelMetaData *)(obj.labels[i]));
        labels_equal = (labels1 == labels2);
    }

    bool defaultPlots_equal = (obj.defaultPlots.size() == defaultPlots.size());
    for(size_t i = 0; (i < defaultPlots.size()) && defaultPlots_equal; ++i)
    {
        // Make references to avtDefaultPlotMetaData from AttributeGroup *.
        const avtDefaultPlotMetaData &defaultPlots1 = *((const avtDefaultPlotMetaData *)(defaultPlots[i]));
        const avtDefaultPlotMetaData &defaultPlots2 = *((const avtDefaultPlotMetaData *)(obj.defaultPlots[i]));
        defaultPlots_equal = (defaultPlots1 == defaultPlots2);
    }

    // Create the return value
    return ((hasTemporalExtents == obj.hasTemporalExtents) &&
            (minTemporalExtents == obj.minTemporalExtents) &&
            (maxTemporalExtents == obj.maxTemporalExtents) &&
            (numStates == obj.numStates) &&
            (isVirtualDatabase == obj.isVirtualDatabase) &&
            (mustRepopulateOnStateChange == obj.mustRepopulateOnStateChange) &&
            (mustAlphabetizeVariables == obj.mustAlphabetizeVariables) &&
            (formatCanDoDomainDecomposition == obj.formatCanDoDomainDecomposition) &&
            (formatCanDoMultires == obj.formatCanDoMultires) &&
            (useCatchAllMesh == obj.useCatchAllMesh) &&
            (timeStepPath == obj.timeStepPath) &&
            (timeStepNames == obj.timeStepNames) &&
            (cycles == obj.cycles) &&
            (cyclesAreAccurate == obj.cyclesAreAccurate) &&
            (times == obj.times) &&
            (timesAreAccurate == obj.timesAreAccurate) &&
            (databaseName == obj.databaseName) &&
            (fileFormat == obj.fileFormat) &&
            (databaseComment == obj.databaseComment) &&
            (exprList == obj.exprList) &&
            meshes_equal &&
            subsets_equal &&
            scalars_equal &&
            vectors_equal &&
            tensors_equal &&
            symmTensors_equal &&
            arrays_equal &&
            materials_equal &&
            species_equal &&
            curves_equal &&
            labels_equal &&
            defaultPlots_equal &&
            (isSimulation == obj.isSimulation) &&
            (simInfo == obj.simInfo) &&
            (suggestedDefaultSILRestriction == obj.suggestedDefaultSILRestriction) &&
            (replacementMask == obj.replacementMask));
}

// ****************************************************************************
// Method: avtDatabaseMetaData::operator !=
//
// Purpose:
//   Comparison operator != for the avtDatabaseMetaData class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

bool
avtDatabaseMetaData::operator != (const avtDatabaseMetaData &obj) const
{
    return !(this->operator == (obj));
}

// ****************************************************************************
// Method: avtDatabaseMetaData::TypeName
//
// Purpose:
//   Type name method for the avtDatabaseMetaData class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

const std::string
avtDatabaseMetaData::TypeName() const
{
    return "avtDatabaseMetaData";
}

// ****************************************************************************
// Method: avtDatabaseMetaData::CopyAttributes
//
// Purpose:
//   CopyAttributes method for the avtDatabaseMetaData class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

bool
avtDatabaseMetaData::CopyAttributes(const AttributeGroup *atts)
{
    if(TypeName() != atts->TypeName())
        return false;

    // Call assignment operator.
    const avtDatabaseMetaData *tmp = (const avtDatabaseMetaData *)atts;
    *this = *tmp;

    return true;
}

// ****************************************************************************
// Method: avtDatabaseMetaData::CreateCompatible
//
// Purpose:
//   CreateCompatible method for the avtDatabaseMetaData class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

AttributeSubject *
avtDatabaseMetaData::CreateCompatible(const std::string &tname) const
{
    AttributeSubject *retval = 0;
    if(TypeName() == tname)
        retval = new avtDatabaseMetaData(*this);
    // Other cases could go here too.

    return retval;
}

// ****************************************************************************
// Method: avtDatabaseMetaData::NewInstance
//
// Purpose:
//   NewInstance method for the avtDatabaseMetaData class.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

AttributeSubject *
avtDatabaseMetaData::NewInstance(bool copy) const
{
    AttributeSubject *retval = 0;
    if(copy)
        retval = new avtDatabaseMetaData(*this);
    else
        retval = new avtDatabaseMetaData;

    return retval;
}

// ****************************************************************************
// Method: avtDatabaseMetaData::SelectAll
//
// Purpose:
//   Selects all attributes.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

void
avtDatabaseMetaData::SelectAll()
{
    Select(ID_hasTemporalExtents,             (void *)&hasTemporalExtents);
    Select(ID_minTemporalExtents,             (void *)&minTemporalExtents);
    Select(ID_maxTemporalExtents,             (void *)&maxTemporalExtents);
    Select(ID_numStates,                      (void *)&numStates);
    Select(ID_isVirtualDatabase,              (void *)&isVirtualDatabase);
    Select(ID_mustRepopulateOnStateChange,    (void *)&mustRepopulateOnStateChange);
    Select(ID_mustAlphabetizeVariables,       (void *)&mustAlphabetizeVariables);
    Select(ID_formatCanDoDomainDecomposition, (void *)&formatCanDoDomainDecomposition);
    Select(ID_formatCanDoMultires,            (void *)&formatCanDoMultires);
    Select(ID_useCatchAllMesh,                (void *)&useCatchAllMesh);
    Select(ID_timeStepPath,                   (void *)&timeStepPath);
    Select(ID_timeStepNames,                  (void *)&timeStepNames);
    Select(ID_cycles,                         (void *)&cycles);
    Select(ID_cyclesAreAccurate,              (void *)&cyclesAreAccurate);
    Select(ID_times,                          (void *)&times);
    Select(ID_timesAreAccurate,               (void *)&timesAreAccurate);
    Select(ID_databaseName,                   (void *)&databaseName);
    Select(ID_fileFormat,                     (void *)&fileFormat);
    Select(ID_databaseComment,                (void *)&databaseComment);
    Select(ID_exprList,                       (void *)&exprList);
    Select(ID_meshes,                         (void *)&meshes);
    Select(ID_subsets,                        (void *)&subsets);
    Select(ID_scalars,                        (void *)&scalars);
    Select(ID_vectors,                        (void *)&vectors);
    Select(ID_tensors,                        (void *)&tensors);
    Select(ID_symmTensors,                    (void *)&symmTensors);
    Select(ID_arrays,                         (void *)&arrays);
    Select(ID_materials,                      (void *)&materials);
    Select(ID_species,                        (void *)&species);
    Select(ID_curves,                         (void *)&curves);
    Select(ID_labels,                         (void *)&labels);
    Select(ID_defaultPlots,                   (void *)&defaultPlots);
    Select(ID_isSimulation,                   (void *)&isSimulation);
    Select(ID_simInfo,                        (void *)&simInfo);
    Select(ID_suggestedDefaultSILRestriction, (void *)&suggestedDefaultSILRestriction);
    Select(ID_replacementMask,                (void *)&replacementMask);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::CreateSubAttributeGroup
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

AttributeGroup *
avtDatabaseMetaData::CreateSubAttributeGroup(int attr_id)
{
    AttributeGroup *retval = 0;
    switch(attr_id)
    {
    case ID_meshes:
        retval = new avtMeshMetaData;
        break;
    case ID_subsets:
        retval = new avtSubsetsMetaData;
        break;
    case ID_scalars:
        retval = new avtScalarMetaData;
        break;
    case ID_vectors:
        retval = new avtVectorMetaData;
        break;
    case ID_tensors:
        retval = new avtTensorMetaData;
        break;
    case ID_symmTensors:
        retval = new avtSymmetricTensorMetaData;
        break;
    case ID_arrays:
        retval = new avtArrayMetaData;
        break;
    case ID_materials:
        retval = new avtMaterialMetaData;
        break;
    case ID_species:
        retval = new avtSpeciesMetaData;
        break;
    case ID_curves:
        retval = new avtCurveMetaData;
        break;
    case ID_labels:
        retval = new avtLabelMetaData;
        break;
    case ID_defaultPlots:
        retval = new avtDefaultPlotMetaData;
        break;
    }

    return retval;
}

///////////////////////////////////////////////////////////////////////////////
// Set property methods
///////////////////////////////////////////////////////////////////////////////

void
avtDatabaseMetaData::SetHasTemporalExtents(bool hasTemporalExtents_)
{
    hasTemporalExtents = hasTemporalExtents_;
    Select(ID_hasTemporalExtents, (void *)&hasTemporalExtents);
}

void
avtDatabaseMetaData::SetMinTemporalExtents(double minTemporalExtents_)
{
    minTemporalExtents = minTemporalExtents_;
    Select(ID_minTemporalExtents, (void *)&minTemporalExtents);
}

void
avtDatabaseMetaData::SetMaxTemporalExtents(double maxTemporalExtents_)
{
    maxTemporalExtents = maxTemporalExtents_;
    Select(ID_maxTemporalExtents, (void *)&maxTemporalExtents);
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::SetNumStates
//
//  Arguments:
//      int   the number of states
//
//  Programmer: Jeremy Meredith
//  Creation:   September 12, 2000
//
//  Modifications:
//    Hank Childs, Mon Mar 11 10:00:14 PST 2002
//    Set up boolean vectors dependent on number of states.
//
//    Brad Whitlock, Tue Mar 25 14:32:13 PST 2003
//    I added the time step names.
//
// ****************************************************************************

void
avtDatabaseMetaData::SetNumStates(int n)
{
    numStates = n;
    cyclesAreAccurate.clear();
    timesAreAccurate.clear();
    cycles.clear();
    times.clear();
    timeStepNames.clear();
    for (int i = 0 ; i < numStates ; i++)
    {
        timeStepNames.push_back("");
        cyclesAreAccurate.push_back(0);
        timesAreAccurate.push_back(0);
        cycles.push_back(0);
        times.push_back(0.);
    }
}

void
avtDatabaseMetaData::SetIsVirtualDatabase(bool isVirtualDatabase_)
{
    isVirtualDatabase = isVirtualDatabase_;
    Select(ID_isVirtualDatabase, (void *)&isVirtualDatabase);
}

void
avtDatabaseMetaData::SetMustRepopulateOnStateChange(bool mustRepopulateOnStateChange_)
{
    mustRepopulateOnStateChange = mustRepopulateOnStateChange_;
    Select(ID_mustRepopulateOnStateChange, (void *)&mustRepopulateOnStateChange);
}

void
avtDatabaseMetaData::SetMustAlphabetizeVariables(bool mustAlphabetizeVariables_)
{
    mustAlphabetizeVariables = mustAlphabetizeVariables_;
    Select(ID_mustAlphabetizeVariables, (void *)&mustAlphabetizeVariables);
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::SetFormatCanDoDomainDecomposition
//
//  Purpose:
//     Sets flag indicating that format can do domain decomposition. This
//     means all meshes should have numBlocks set to 1. Upon each attempt to
//     get data from the database, the format can decide how to decompose
//     the data across processors. This also means that when VisIt
//     "load-balances" blocks (i.e. domains) across processors, it will do so
//     by assigning the one and only block to each and every processor. It
//     is up to the plugin to decide which portion of the whole it will
//     actually return in a request to GetMesh(), GetVar(), ...
//
//  Programmer:  Mark C. Miller
//  Creation:    September 20, 2004
// ****************************************************************************

void
avtDatabaseMetaData::SetFormatCanDoDomainDecomposition(bool can)
{
    if (can)
    {
        // see if there are any meshes with other than a single block
        bool someMeshesHaveOtherThanOneBlock = false;
        for (int i = 0; i < GetNumMeshes(); i++)
        {
            if (GetMeshes(i).numBlocks != 1)
            {
                someMeshesHaveOtherThanOneBlock = true;
                break;
            }
        }

        if (someMeshesHaveOtherThanOneBlock)
        {
            EXCEPTION1(ImproperUseException, "Format cannot do domain "
                "decomposition with meshes having other than a single block");
        }
    }

    formatCanDoDomainDecomposition = can;
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::SetFormatCanDoMultires
//
//  Purpose:
//     Sets flag indicating that format can provide multiple resolutions
//     of the data. This means all meshes should have numBlocks set to 1.
//     Upon each attempt to get data from the database, the format can decide
//     what resolution of the data to provide and how to decompose the data
//     across processors. This also means that when VisIt "load-balances"
//     blocks (i.e. domains) across processors, it will do so by assigning
//     the one and only block to each and every processor. It is up to the
//     plugin to decide which portion of the whole it will actually return
//     in a request to GetMesh(), GetVar(), ...
//
//  Programmer:  Eric Brugger
//  Creation:    December 20, 2013
// ****************************************************************************

void
avtDatabaseMetaData::SetFormatCanDoMultires(bool can)
{
    if (can)
    {
        // see if there are any meshes with other than a single block
        bool someMeshesHaveOtherThanOneBlock = false;
        for (int i = 0; i < GetNumMeshes(); i++)
        {
            if (GetMeshes(i).numBlocks != 1)
            {
                someMeshesHaveOtherThanOneBlock = true;
                break;
            }
        }

        if (someMeshesHaveOtherThanOneBlock)
        {
            EXCEPTION1(ImproperUseException, "Format cannot provide "
                "multiple resolutions of the data with meshes having other "
                "than a single block");
        }
    }

    formatCanDoMultires = can;
    Select(ID_formatCanDoMultires, (void *)&formatCanDoMultires);
}

void
avtDatabaseMetaData::SetUseCatchAllMesh(bool useCatchAllMesh_)
{
    useCatchAllMesh = useCatchAllMesh_;
    Select(ID_useCatchAllMesh, (void *)&useCatchAllMesh);
}

void
avtDatabaseMetaData::SetTimeStepPath(const std::string &timeStepPath_)
{
    timeStepPath = timeStepPath_;
    Select(ID_timeStepPath, (void *)&timeStepPath);
}

void
avtDatabaseMetaData::SetTimeStepNames(const stringVector &timeStepNames_)
{
    timeStepNames = timeStepNames_;
    Select(ID_timeStepNames, (void *)&timeStepNames);
}

void
avtDatabaseMetaData::SetCycles(const intVector &cycles_)
{
    cycles = cycles_;
    Select(ID_cycles, (void *)&cycles);
}

void
avtDatabaseMetaData::SetCyclesAreAccurate(const intVector &cyclesAreAccurate_)
{
    cyclesAreAccurate = cyclesAreAccurate_;
    Select(ID_cyclesAreAccurate, (void *)&cyclesAreAccurate);
}

void
avtDatabaseMetaData::SetTimes(const doubleVector &times_)
{
    times = times_;
    Select(ID_times, (void *)&times);
}

void
avtDatabaseMetaData::SetTimesAreAccurate(const intVector &timesAreAccurate_)
{
    timesAreAccurate = timesAreAccurate_;
    Select(ID_timesAreAccurate, (void *)&timesAreAccurate);
}

void
avtDatabaseMetaData::SetDatabaseName(const std::string &databaseName_)
{
    databaseName = databaseName_;
    Select(ID_databaseName, (void *)&databaseName);
}

void
avtDatabaseMetaData::SetFileFormat(const std::string &fileFormat_)
{
    fileFormat = fileFormat_;
    Select(ID_fileFormat, (void *)&fileFormat);
}

void
avtDatabaseMetaData::SetDatabaseComment(const std::string &databaseComment_)
{
    databaseComment = databaseComment_;
    Select(ID_databaseComment, (void *)&databaseComment);
}

void
avtDatabaseMetaData::SetExprList(const ExpressionList &exprList_)
{
    exprList = exprList_;
    Select(ID_exprList, (void *)&exprList);
}

void
avtDatabaseMetaData::SetIsSimulation(bool isSimulation_)
{
    isSimulation = isSimulation_;
    Select(ID_isSimulation, (void *)&isSimulation);
}

void
avtDatabaseMetaData::SetSimInfo(const avtSimulationInformation &simInfo_)
{
    simInfo = simInfo_;
    Select(ID_simInfo, (void *)&simInfo);
}

void
avtDatabaseMetaData::SetSuggestedDefaultSILRestriction(const stringVector &suggestedDefaultSILRestriction_)
{
    suggestedDefaultSILRestriction = suggestedDefaultSILRestriction_;
    Select(ID_suggestedDefaultSILRestriction, (void *)&suggestedDefaultSILRestriction);
}

void
avtDatabaseMetaData::SetReplacementMask(int replacementMask_)
{
    replacementMask = replacementMask_;
    Select(ID_replacementMask, (void *)&replacementMask);
}

///////////////////////////////////////////////////////////////////////////////
// Get property methods
///////////////////////////////////////////////////////////////////////////////

bool
avtDatabaseMetaData::GetHasTemporalExtents() const
{
    return hasTemporalExtents;
}

double
avtDatabaseMetaData::GetMinTemporalExtents() const
{
    return minTemporalExtents;
}

double
avtDatabaseMetaData::GetMaxTemporalExtents() const
{
    return maxTemporalExtents;
}

int
avtDatabaseMetaData::GetNumStates() const
{
    return numStates;
}

bool
avtDatabaseMetaData::GetIsVirtualDatabase() const
{
    return isVirtualDatabase;
}

bool
avtDatabaseMetaData::GetMustRepopulateOnStateChange() const
{
    return mustRepopulateOnStateChange;
}

bool
avtDatabaseMetaData::GetMustAlphabetizeVariables() const
{
    return mustAlphabetizeVariables;
}

bool
avtDatabaseMetaData::GetFormatCanDoDomainDecomposition() const
{
    return formatCanDoDomainDecomposition;
}

bool
avtDatabaseMetaData::GetFormatCanDoMultires() const
{
    return formatCanDoMultires;
}

bool
avtDatabaseMetaData::GetUseCatchAllMesh() const
{
    return useCatchAllMesh;
}

const std::string &
avtDatabaseMetaData::GetTimeStepPath() const
{
    return timeStepPath;
}

std::string &
avtDatabaseMetaData::GetTimeStepPath()
{
    return timeStepPath;
}

const stringVector &
avtDatabaseMetaData::GetTimeStepNames() const
{
    return timeStepNames;
}

stringVector &
avtDatabaseMetaData::GetTimeStepNames()
{
    return timeStepNames;
}

const intVector &
avtDatabaseMetaData::GetCycles() const
{
    return cycles;
}

intVector &
avtDatabaseMetaData::GetCycles()
{
    return cycles;
}

const intVector &
avtDatabaseMetaData::GetCyclesAreAccurate() const
{
    return cyclesAreAccurate;
}

intVector &
avtDatabaseMetaData::GetCyclesAreAccurate()
{
    return cyclesAreAccurate;
}

const doubleVector &
avtDatabaseMetaData::GetTimes() const
{
    return times;
}

doubleVector &
avtDatabaseMetaData::GetTimes()
{
    return times;
}

const intVector &
avtDatabaseMetaData::GetTimesAreAccurate() const
{
    return timesAreAccurate;
}

intVector &
avtDatabaseMetaData::GetTimesAreAccurate()
{
    return timesAreAccurate;
}

const std::string &
avtDatabaseMetaData::GetDatabaseName() const
{
    return databaseName;
}

std::string &
avtDatabaseMetaData::GetDatabaseName()
{
    return databaseName;
}

const std::string &
avtDatabaseMetaData::GetFileFormat() const
{
    return fileFormat;
}

std::string &
avtDatabaseMetaData::GetFileFormat()
{
    return fileFormat;
}

const std::string &
avtDatabaseMetaData::GetDatabaseComment() const
{
    return databaseComment;
}

std::string &
avtDatabaseMetaData::GetDatabaseComment()
{
    return databaseComment;
}

const ExpressionList &
avtDatabaseMetaData::GetExprList() const
{
    return exprList;
}

ExpressionList &
avtDatabaseMetaData::GetExprList()
{
    return exprList;
}

const AttributeGroupVector &
avtDatabaseMetaData::GetMeshes() const
{
    return meshes;
}

AttributeGroupVector &
avtDatabaseMetaData::GetMeshes()
{
    return meshes;
}

const AttributeGroupVector &
avtDatabaseMetaData::GetSubsets() const
{
    return subsets;
}

AttributeGroupVector &
avtDatabaseMetaData::GetSubsets()
{
    return subsets;
}

const AttributeGroupVector &
avtDatabaseMetaData::GetScalars() const
{
    return scalars;
}

AttributeGroupVector &
avtDatabaseMetaData::GetScalars()
{
    return scalars;
}

const AttributeGroupVector &
avtDatabaseMetaData::GetVectors() const
{
    return vectors;
}

AttributeGroupVector &
avtDatabaseMetaData::GetVectors()
{
    return vectors;
}

const AttributeGroupVector &
avtDatabaseMetaData::GetTensors() const
{
    return tensors;
}

AttributeGroupVector &
avtDatabaseMetaData::GetTensors()
{
    return tensors;
}

const AttributeGroupVector &
avtDatabaseMetaData::GetSymmTensors() const
{
    return symmTensors;
}

AttributeGroupVector &
avtDatabaseMetaData::GetSymmTensors()
{
    return symmTensors;
}

const AttributeGroupVector &
avtDatabaseMetaData::GetArrays() const
{
    return arrays;
}

AttributeGroupVector &
avtDatabaseMetaData::GetArrays()
{
    return arrays;
}

const AttributeGroupVector &
avtDatabaseMetaData::GetMaterials() const
{
    return materials;
}

AttributeGroupVector &
avtDatabaseMetaData::GetMaterials()
{
    return materials;
}

const AttributeGroupVector &
avtDatabaseMetaData::GetSpecies() const
{
    return species;
}

AttributeGroupVector &
avtDatabaseMetaData::GetSpecies()
{
    return species;
}

const AttributeGroupVector &
avtDatabaseMetaData::GetCurves() const
{
    return curves;
}

AttributeGroupVector &
avtDatabaseMetaData::GetCurves()
{
    return curves;
}

const AttributeGroupVector &
avtDatabaseMetaData::GetLabels() const
{
    return labels;
}

AttributeGroupVector &
avtDatabaseMetaData::GetLabels()
{
    return labels;
}

const AttributeGroupVector &
avtDatabaseMetaData::GetDefaultPlots() const
{
    return defaultPlots;
}

AttributeGroupVector &
avtDatabaseMetaData::GetDefaultPlots()
{
    return defaultPlots;
}

bool
avtDatabaseMetaData::GetIsSimulation() const
{
    return isSimulation;
}

const avtSimulationInformation &
avtDatabaseMetaData::GetSimInfo() const
{
    return simInfo;
}

avtSimulationInformation &
avtDatabaseMetaData::GetSimInfo()
{
    return simInfo;
}

const stringVector &
avtDatabaseMetaData::GetSuggestedDefaultSILRestriction() const
{
    return suggestedDefaultSILRestriction;
}

stringVector &
avtDatabaseMetaData::GetSuggestedDefaultSILRestriction()
{
    return suggestedDefaultSILRestriction;
}

int
avtDatabaseMetaData::GetReplacementMask() const
{
    return replacementMask;
}

///////////////////////////////////////////////////////////////////////////////
// Select property methods
///////////////////////////////////////////////////////////////////////////////

void
avtDatabaseMetaData::SelectTimeStepPath()
{
    Select(ID_timeStepPath, (void *)&timeStepPath);
}

void
avtDatabaseMetaData::SelectTimeStepNames()
{
    Select(ID_timeStepNames, (void *)&timeStepNames);
}

void
avtDatabaseMetaData::SelectCycles()
{
    Select(ID_cycles, (void *)&cycles);
}

void
avtDatabaseMetaData::SelectCyclesAreAccurate()
{
    Select(ID_cyclesAreAccurate, (void *)&cyclesAreAccurate);
}

void
avtDatabaseMetaData::SelectTimes()
{
    Select(ID_times, (void *)&times);
}

void
avtDatabaseMetaData::SelectTimesAreAccurate()
{
    Select(ID_timesAreAccurate, (void *)&timesAreAccurate);
}

void
avtDatabaseMetaData::SelectDatabaseName()
{
    Select(ID_databaseName, (void *)&databaseName);
}

void
avtDatabaseMetaData::SelectFileFormat()
{
    Select(ID_fileFormat, (void *)&fileFormat);
}

void
avtDatabaseMetaData::SelectDatabaseComment()
{
    Select(ID_databaseComment, (void *)&databaseComment);
}

void
avtDatabaseMetaData::SelectExprList()
{
    Select(ID_exprList, (void *)&exprList);
}

void
avtDatabaseMetaData::SelectMeshes()
{
    Select(ID_meshes, (void *)&meshes);
}

void
avtDatabaseMetaData::SelectSubsets()
{
    Select(ID_subsets, (void *)&subsets);
}

void
avtDatabaseMetaData::SelectScalars()
{
    Select(ID_scalars, (void *)&scalars);
}

void
avtDatabaseMetaData::SelectVectors()
{
    Select(ID_vectors, (void *)&vectors);
}

void
avtDatabaseMetaData::SelectTensors()
{
    Select(ID_tensors, (void *)&tensors);
}

void
avtDatabaseMetaData::SelectSymmTensors()
{
    Select(ID_symmTensors, (void *)&symmTensors);
}

void
avtDatabaseMetaData::SelectArrays()
{
    Select(ID_arrays, (void *)&arrays);
}

void
avtDatabaseMetaData::SelectMaterials()
{
    Select(ID_materials, (void *)&materials);
}

void
avtDatabaseMetaData::SelectSpecies()
{
    Select(ID_species, (void *)&species);
}

void
avtDatabaseMetaData::SelectCurves()
{
    Select(ID_curves, (void *)&curves);
}

void
avtDatabaseMetaData::SelectLabels()
{
    Select(ID_labels, (void *)&labels);
}

void
avtDatabaseMetaData::SelectDefaultPlots()
{
    Select(ID_defaultPlots, (void *)&defaultPlots);
}

void
avtDatabaseMetaData::SelectSimInfo()
{
    Select(ID_simInfo, (void *)&simInfo);
}

void
avtDatabaseMetaData::SelectSuggestedDefaultSILRestriction()
{
    Select(ID_suggestedDefaultSILRestriction, (void *)&suggestedDefaultSILRestriction);
}

///////////////////////////////////////////////////////////////////////////////
// AttributeGroupVector convenience methods.
///////////////////////////////////////////////////////////////////////////////

// ****************************************************************************
// Method: avtDatabaseMetaData::AddMeshes
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

void
avtDatabaseMetaData::AddMeshes(const avtMeshMetaData &obj)
{
    avtMeshMetaData *newavtMeshMetaData = new avtMeshMetaData(obj);
    meshes.push_back(newavtMeshMetaData);

    // Indicate that things have changed by selecting it.
    Select(ID_meshes, (void *)&meshes);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::ClearMeshes
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

void
avtDatabaseMetaData::ClearMeshes()
{
    AttributeGroupVector::iterator pos;

    for(pos = meshes.begin(); pos != meshes.end(); ++pos)
        delete *pos;
    meshes.clear();

    // Indicate that things have changed by selecting the list.
    Select(ID_meshes, (void *)&meshes);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::RemoveMeshes
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

void
avtDatabaseMetaData::RemoveMeshes(int index)
{
    AttributeGroupVector::iterator pos = meshes.begin();

    // Iterate through the vector "index" times.
    for(int i = 0; i < index; ++i)
        if(pos != meshes.end()) ++pos;

    // If pos is still a valid iterator, remove that element.
    if(pos != meshes.end())
    {
        delete *pos;
        meshes.erase(pos);
    }

    // Indicate that things have changed by selecting the list.
    Select(ID_meshes, (void *)&meshes);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::GetNumMeshes
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

int
avtDatabaseMetaData::GetNumMeshes() const
{
    return (int)meshes.size();
}

// ****************************************************************************
// Method: avtDatabaseMetaData::GetMeshes
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

avtMeshMetaData &
avtDatabaseMetaData::GetMeshes(int i)
{
    return *((avtMeshMetaData *)meshes[i]);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::GetMeshes
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

const avtMeshMetaData &
avtDatabaseMetaData::GetMeshes(int i) const
{
    return *((avtMeshMetaData *)meshes[i]);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::AddSubsets
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

void
avtDatabaseMetaData::AddSubsets(const avtSubsetsMetaData &obj)
{
    avtSubsetsMetaData *newavtSubsetsMetaData = new avtSubsetsMetaData(obj);
    subsets.push_back(newavtSubsetsMetaData);

    // Indicate that things have changed by selecting it.
    Select(ID_subsets, (void *)&subsets);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::ClearSubsets
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

void
avtDatabaseMetaData::ClearSubsets()
{
    AttributeGroupVector::iterator pos;

    for(pos = subsets.begin(); pos != subsets.end(); ++pos)
        delete *pos;
    subsets.clear();

    // Indicate that things have changed by selecting the list.
    Select(ID_subsets, (void *)&subsets);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::RemoveSubsets
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

void
avtDatabaseMetaData::RemoveSubsets(int index)
{
    AttributeGroupVector::iterator pos = subsets.begin();

    // Iterate through the vector "index" times.
    for(int i = 0; i < index; ++i)
        if(pos != subsets.end()) ++pos;

    // If pos is still a valid iterator, remove that element.
    if(pos != subsets.end())
    {
        delete *pos;
        subsets.erase(pos);
    }

    // Indicate that things have changed by selecting the list.
    Select(ID_subsets, (void *)&subsets);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::GetNumSubsets
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

int
avtDatabaseMetaData::GetNumSubsets() const
{
    return (int)subsets.size();
}

// ****************************************************************************
// Method: avtDatabaseMetaData::GetSubsets
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

avtSubsetsMetaData &
avtDatabaseMetaData::GetSubsets(int i)
{
    return *((avtSubsetsMetaData *)subsets[i]);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::GetSubsets
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

const avtSubsetsMetaData &
avtDatabaseMetaData::GetSubsets(int i) const
{
    return *((avtSubsetsMetaData *)subsets[i]);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::AddScalars
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

void
avtDatabaseMetaData::AddScalars(const avtScalarMetaData &obj)
{
    avtScalarMetaData *newavtScalarMetaData = new avtScalarMetaData(obj);
    scalars.push_back(newavtScalarMetaData);

    // Indicate that things have changed by selecting it.
    Select(ID_scalars, (void *)&scalars);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::ClearScalars
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

void
avtDatabaseMetaData::ClearScalars()
{
    AttributeGroupVector::iterator pos;

    for(pos = scalars.begin(); pos != scalars.end(); ++pos)
        delete *pos;
    scalars.clear();

    // Indicate that things have changed by selecting the list.
    Select(ID_scalars, (void *)&scalars);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::RemoveScalars
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

void
avtDatabaseMetaData::RemoveScalars(int index)
{
    AttributeGroupVector::iterator pos = scalars.begin();

    // Iterate through the vector "index" times.
    for(int i = 0; i < index; ++i)
        if(pos != scalars.end()) ++pos;

    // If pos is still a valid iterator, remove that element.
    if(pos != scalars.end())
    {
        delete *pos;
        scalars.erase(pos);
    }

    // Indicate that things have changed by selecting the list.
    Select(ID_scalars, (void *)&scalars);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::GetNumScalars
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

int
avtDatabaseMetaData::GetNumScalars() const
{
    return (int)scalars.size();
}

// ****************************************************************************
// Method: avtDatabaseMetaData::GetScalars
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

avtScalarMetaData &
avtDatabaseMetaData::GetScalars(int i)
{
    return *((avtScalarMetaData *)scalars[i]);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::GetScalars
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

const avtScalarMetaData &
avtDatabaseMetaData::GetScalars(int i) const
{
    return *((avtScalarMetaData *)scalars[i]);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::AddVectors
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

void
avtDatabaseMetaData::AddVectors(const avtVectorMetaData &obj)
{
    avtVectorMetaData *newavtVectorMetaData = new avtVectorMetaData(obj);
    vectors.push_back(newavtVectorMetaData);

    // Indicate that things have changed by selecting it.
    Select(ID_vectors, (void *)&vectors);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::ClearVectors
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

void
avtDatabaseMetaData::ClearVectors()
{
    AttributeGroupVector::iterator pos;

    for(pos = vectors.begin(); pos != vectors.end(); ++pos)
        delete *pos;
    vectors.clear();

    // Indicate that things have changed by selecting the list.
    Select(ID_vectors, (void *)&vectors);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::RemoveVectors
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

void
avtDatabaseMetaData::RemoveVectors(int index)
{
    AttributeGroupVector::iterator pos = vectors.begin();

    // Iterate through the vector "index" times.
    for(int i = 0; i < index; ++i)
        if(pos != vectors.end()) ++pos;

    // If pos is still a valid iterator, remove that element.
    if(pos != vectors.end())
    {
        delete *pos;
        vectors.erase(pos);
    }

    // Indicate that things have changed by selecting the list.
    Select(ID_vectors, (void *)&vectors);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::GetNumVectors
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

int
avtDatabaseMetaData::GetNumVectors() const
{
    return (int)vectors.size();
}

// ****************************************************************************
// Method: avtDatabaseMetaData::GetVectors
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

avtVectorMetaData &
avtDatabaseMetaData::GetVectors(int i)
{
    return *((avtVectorMetaData *)vectors[i]);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::GetVectors
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

const avtVectorMetaData &
avtDatabaseMetaData::GetVectors(int i) const
{
    return *((avtVectorMetaData *)vectors[i]);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::AddTensors
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

void
avtDatabaseMetaData::AddTensors(const avtTensorMetaData &obj)
{
    avtTensorMetaData *newavtTensorMetaData = new avtTensorMetaData(obj);
    tensors.push_back(newavtTensorMetaData);

    // Indicate that things have changed by selecting it.
    Select(ID_tensors, (void *)&tensors);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::ClearTensors
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

void
avtDatabaseMetaData::ClearTensors()
{
    AttributeGroupVector::iterator pos;

    for(pos = tensors.begin(); pos != tensors.end(); ++pos)
        delete *pos;
    tensors.clear();

    // Indicate that things have changed by selecting the list.
    Select(ID_tensors, (void *)&tensors);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::RemoveTensors
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

void
avtDatabaseMetaData::RemoveTensors(int index)
{
    AttributeGroupVector::iterator pos = tensors.begin();

    // Iterate through the vector "index" times.
    for(int i = 0; i < index; ++i)
        if(pos != tensors.end()) ++pos;

    // If pos is still a valid iterator, remove that element.
    if(pos != tensors.end())
    {
        delete *pos;
        tensors.erase(pos);
    }

    // Indicate that things have changed by selecting the list.
    Select(ID_tensors, (void *)&tensors);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::GetNumTensors
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

int
avtDatabaseMetaData::GetNumTensors() const
{
    return (int)tensors.size();
}

// ****************************************************************************
// Method: avtDatabaseMetaData::GetTensors
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

avtTensorMetaData &
avtDatabaseMetaData::GetTensors(int i)
{
    return *((avtTensorMetaData *)tensors[i]);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::GetTensors
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

const avtTensorMetaData &
avtDatabaseMetaData::GetTensors(int i) const
{
    return *((avtTensorMetaData *)tensors[i]);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::AddSymmTensors
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

void
avtDatabaseMetaData::AddSymmTensors(const avtSymmetricTensorMetaData &obj)
{
    avtSymmetricTensorMetaData *newavtSymmetricTensorMetaData = new avtSymmetricTensorMetaData(obj);
    symmTensors.push_back(newavtSymmetricTensorMetaData);

    // Indicate that things have changed by selecting it.
    Select(ID_symmTensors, (void *)&symmTensors);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::ClearSymmTensors
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

void
avtDatabaseMetaData::ClearSymmTensors()
{
    AttributeGroupVector::iterator pos;

    for(pos = symmTensors.begin(); pos != symmTensors.end(); ++pos)
        delete *pos;
    symmTensors.clear();

    // Indicate that things have changed by selecting the list.
    Select(ID_symmTensors, (void *)&symmTensors);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::RemoveSymmTensors
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

void
avtDatabaseMetaData::RemoveSymmTensors(int index)
{
    AttributeGroupVector::iterator pos = symmTensors.begin();

    // Iterate through the vector "index" times.
    for(int i = 0; i < index; ++i)
        if(pos != symmTensors.end()) ++pos;

    // If pos is still a valid iterator, remove that element.
    if(pos != symmTensors.end())
    {
        delete *pos;
        symmTensors.erase(pos);
    }

    // Indicate that things have changed by selecting the list.
    Select(ID_symmTensors, (void *)&symmTensors);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::GetNumSymmTensors
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

int
avtDatabaseMetaData::GetNumSymmTensors() const
{
    return (int)symmTensors.size();
}

// ****************************************************************************
// Method: avtDatabaseMetaData::GetSymmTensors
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

avtSymmetricTensorMetaData &
avtDatabaseMetaData::GetSymmTensors(int i)
{
    return *((avtSymmetricTensorMetaData *)symmTensors[i]);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::GetSymmTensors
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

const avtSymmetricTensorMetaData &
avtDatabaseMetaData::GetSymmTensors(int i) const
{
    return *((avtSymmetricTensorMetaData *)symmTensors[i]);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::AddArrays
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

void
avtDatabaseMetaData::AddArrays(const avtArrayMetaData &obj)
{
    avtArrayMetaData *newavtArrayMetaData = new avtArrayMetaData(obj);
    arrays.push_back(newavtArrayMetaData);

    // Indicate that things have changed by selecting it.
    Select(ID_arrays, (void *)&arrays);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::ClearArrays
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

void
avtDatabaseMetaData::ClearArrays()
{
    AttributeGroupVector::iterator pos;

    for(pos = arrays.begin(); pos != arrays.end(); ++pos)
        delete *pos;
    arrays.clear();

    // Indicate that things have changed by selecting the list.
    Select(ID_arrays, (void *)&arrays);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::RemoveArrays
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

void
avtDatabaseMetaData::RemoveArrays(int index)
{
    AttributeGroupVector::iterator pos = arrays.begin();

    // Iterate through the vector "index" times.
    for(int i = 0; i < index; ++i)
        if(pos != arrays.end()) ++pos;

    // If pos is still a valid iterator, remove that element.
    if(pos != arrays.end())
    {
        delete *pos;
        arrays.erase(pos);
    }

    // Indicate that things have changed by selecting the list.
    Select(ID_arrays, (void *)&arrays);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::GetNumArrays
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

int
avtDatabaseMetaData::GetNumArrays() const
{
    return (int)arrays.size();
}

// ****************************************************************************
// Method: avtDatabaseMetaData::GetArrays
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

avtArrayMetaData &
avtDatabaseMetaData::GetArrays(int i)
{
    return *((avtArrayMetaData *)arrays[i]);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::GetArrays
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

const avtArrayMetaData &
avtDatabaseMetaData::GetArrays(int i) const
{
    return *((avtArrayMetaData *)arrays[i]);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::AddMaterials
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

void
avtDatabaseMetaData::AddMaterials(const avtMaterialMetaData &obj)
{
    avtMaterialMetaData *newavtMaterialMetaData = new avtMaterialMetaData(obj);
    materials.push_back(newavtMaterialMetaData);

    // Indicate that things have changed by selecting it.
    Select(ID_materials, (void *)&materials);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::ClearMaterials
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

void
avtDatabaseMetaData::ClearMaterials()
{
    AttributeGroupVector::iterator pos;

    for(pos = materials.begin(); pos != materials.end(); ++pos)
        delete *pos;
    materials.clear();

    // Indicate that things have changed by selecting the list.
    Select(ID_materials, (void *)&materials);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::RemoveMaterials
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

void
avtDatabaseMetaData::RemoveMaterials(int index)
{
    AttributeGroupVector::iterator pos = materials.begin();

    // Iterate through the vector "index" times.
    for(int i = 0; i < index; ++i)
        if(pos != materials.end()) ++pos;

    // If pos is still a valid iterator, remove that element.
    if(pos != materials.end())
    {
        delete *pos;
        materials.erase(pos);
    }

    // Indicate that things have changed by selecting the list.
    Select(ID_materials, (void *)&materials);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::GetNumMaterials
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

int
avtDatabaseMetaData::GetNumMaterials() const
{
    return (int)materials.size();
}

// ****************************************************************************
// Method: avtDatabaseMetaData::GetMaterials
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

avtMaterialMetaData &
avtDatabaseMetaData::GetMaterials(int i)
{
    return *((avtMaterialMetaData *)materials[i]);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::GetMaterials
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

const avtMaterialMetaData &
avtDatabaseMetaData::GetMaterials(int i) const
{
    return *((avtMaterialMetaData *)materials[i]);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::AddSpecies
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

void
avtDatabaseMetaData::AddSpecies(const avtSpeciesMetaData &obj)
{
    avtSpeciesMetaData *newavtSpeciesMetaData = new avtSpeciesMetaData(obj);
    species.push_back(newavtSpeciesMetaData);

    // Indicate that things have changed by selecting it.
    Select(ID_species, (void *)&species);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::ClearSpecies
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

void
avtDatabaseMetaData::ClearSpecies()
{
    AttributeGroupVector::iterator pos;

    for(pos = species.begin(); pos != species.end(); ++pos)
        delete *pos;
    species.clear();

    // Indicate that things have changed by selecting the list.
    Select(ID_species, (void *)&species);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::RemoveSpecies
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

void
avtDatabaseMetaData::RemoveSpecies(int index)
{
    AttributeGroupVector::iterator pos = species.begin();

    // Iterate through the vector "index" times.
    for(int i = 0; i < index; ++i)
        if(pos != species.end()) ++pos;

    // If pos is still a valid iterator, remove that element.
    if(pos != species.end())
    {
        delete *pos;
        species.erase(pos);
    }

    // Indicate that things have changed by selecting the list.
    Select(ID_species, (void *)&species);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::GetNumSpecies
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

int
avtDatabaseMetaData::GetNumSpecies() const
{
    return (int)species.size();
}

// ****************************************************************************
// Method: avtDatabaseMetaData::GetSpecies
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

avtSpeciesMetaData &
avtDatabaseMetaData::GetSpecies(int i)
{
    return *((avtSpeciesMetaData *)species[i]);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::GetSpecies
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

const avtSpeciesMetaData &
avtDatabaseMetaData::GetSpecies(int i) const
{
    return *((avtSpeciesMetaData *)species[i]);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::AddCurves
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

void
avtDatabaseMetaData::AddCurves(const avtCurveMetaData &obj)
{
    avtCurveMetaData *newavtCurveMetaData = new avtCurveMetaData(obj);
    curves.push_back(newavtCurveMetaData);

    // Indicate that things have changed by selecting it.
    Select(ID_curves, (void *)&curves);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::ClearCurves
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

void
avtDatabaseMetaData::ClearCurves()
{
    AttributeGroupVector::iterator pos;

    for(pos = curves.begin(); pos != curves.end(); ++pos)
        delete *pos;
    curves.clear();

    // Indicate that things have changed by selecting the list.
    Select(ID_curves, (void *)&curves);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::RemoveCurves
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

void
avtDatabaseMetaData::RemoveCurves(int index)
{
    AttributeGroupVector::iterator pos = curves.begin();

    // Iterate through the vector "index" times.
    for(int i = 0; i < index; ++i)
        if(pos != curves.end()) ++pos;

    // If pos is still a valid iterator, remove that element.
    if(pos != curves.end())
    {
        delete *pos;
        curves.erase(pos);
    }

    // Indicate that things have changed by selecting the list.
    Select(ID_curves, (void *)&curves);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::GetNumCurves
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

int
avtDatabaseMetaData::GetNumCurves() const
{
    return (int)curves.size();
}

// ****************************************************************************
// Method: avtDatabaseMetaData::GetCurves
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

avtCurveMetaData &
avtDatabaseMetaData::GetCurves(int i)
{
    return *((avtCurveMetaData *)curves[i]);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::GetCurves
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

const avtCurveMetaData &
avtDatabaseMetaData::GetCurves(int i) const
{
    return *((avtCurveMetaData *)curves[i]);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::AddLabels
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

void
avtDatabaseMetaData::AddLabels(const avtLabelMetaData &obj)
{
    avtLabelMetaData *newavtLabelMetaData = new avtLabelMetaData(obj);
    labels.push_back(newavtLabelMetaData);

    // Indicate that things have changed by selecting it.
    Select(ID_labels, (void *)&labels);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::ClearLabels
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

void
avtDatabaseMetaData::ClearLabels()
{
    AttributeGroupVector::iterator pos;

    for(pos = labels.begin(); pos != labels.end(); ++pos)
        delete *pos;
    labels.clear();

    // Indicate that things have changed by selecting the list.
    Select(ID_labels, (void *)&labels);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::RemoveLabels
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

void
avtDatabaseMetaData::RemoveLabels(int index)
{
    AttributeGroupVector::iterator pos = labels.begin();

    // Iterate through the vector "index" times.
    for(int i = 0; i < index; ++i)
        if(pos != labels.end()) ++pos;

    // If pos is still a valid iterator, remove that element.
    if(pos != labels.end())
    {
        delete *pos;
        labels.erase(pos);
    }

    // Indicate that things have changed by selecting the list.
    Select(ID_labels, (void *)&labels);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::GetNumLabels
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

int
avtDatabaseMetaData::GetNumLabels() const
{
    return (int)labels.size();
}

// ****************************************************************************
// Method: avtDatabaseMetaData::GetLabels
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

avtLabelMetaData &
avtDatabaseMetaData::GetLabels(int i)
{
    return *((avtLabelMetaData *)labels[i]);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::GetLabels
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

const avtLabelMetaData &
avtDatabaseMetaData::GetLabels(int i) const
{
    return *((avtLabelMetaData *)labels[i]);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::AddDefaultPlots
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

void
avtDatabaseMetaData::AddDefaultPlots(const avtDefaultPlotMetaData &obj)
{
    avtDefaultPlotMetaData *newavtDefaultPlotMetaData = new avtDefaultPlotMetaData(obj);
    defaultPlots.push_back(newavtDefaultPlotMetaData);

    // Indicate that things have changed by selecting it.
    Select(ID_defaultPlots, (void *)&defaultPlots);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::ClearDefaultPlots
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

void
avtDatabaseMetaData::ClearDefaultPlots()
{
    AttributeGroupVector::iterator pos;

    for(pos = defaultPlots.begin(); pos != defaultPlots.end(); ++pos)
        delete *pos;
    defaultPlots.clear();

    // Indicate that things have changed by selecting the list.
    Select(ID_defaultPlots, (void *)&defaultPlots);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::RemoveDefaultPlots
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

void
avtDatabaseMetaData::RemoveDefaultPlots(int index)
{
    AttributeGroupVector::iterator pos = defaultPlots.begin();

    // Iterate through the vector "index" times.
    for(int i = 0; i < index; ++i)
        if(pos != defaultPlots.end()) ++pos;

    // If pos is still a valid iterator, remove that element.
    if(pos != defaultPlots.end())
    {
        delete *pos;
        defaultPlots.erase(pos);
    }

    // Indicate that things have changed by selecting the list.
    Select(ID_defaultPlots, (void *)&defaultPlots);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::GetNumDefaultPlots
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

int
avtDatabaseMetaData::GetNumDefaultPlots() const
{
    return (int)defaultPlots.size();
}

// ****************************************************************************
// Method: avtDatabaseMetaData::GetDefaultPlots
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

avtDefaultPlotMetaData &
avtDatabaseMetaData::GetDefaultPlots(int i)
{
    return *((avtDefaultPlotMetaData *)defaultPlots[i]);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::GetDefaultPlots
//
// Purpose:
//   Contains database metadata attributes
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

const avtDefaultPlotMetaData &
avtDatabaseMetaData::GetDefaultPlots(int i) const
{
    return *((avtDefaultPlotMetaData *)defaultPlots[i]);
}

///////////////////////////////////////////////////////////////////////////////
// Keyframing methods
///////////////////////////////////////////////////////////////////////////////

// ****************************************************************************
// Method: avtDatabaseMetaData::GetFieldName
//
// Purpose:
//   This method returns the name of a field given its index.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

std::string
avtDatabaseMetaData::GetFieldName(int index) const
{
    switch (index)
    {
    case ID_hasTemporalExtents:             return "hasTemporalExtents";
    case ID_minTemporalExtents:             return "minTemporalExtents";
    case ID_maxTemporalExtents:             return "maxTemporalExtents";
    case ID_numStates:                      return "numStates";
    case ID_isVirtualDatabase:              return "isVirtualDatabase";
    case ID_mustRepopulateOnStateChange:    return "mustRepopulateOnStateChange";
    case ID_mustAlphabetizeVariables:       return "mustAlphabetizeVariables";
    case ID_formatCanDoDomainDecomposition: return "formatCanDoDomainDecomposition";
    case ID_formatCanDoMultires:            return "formatCanDoMultires";
    case ID_useCatchAllMesh:                return "useCatchAllMesh";
    case ID_timeStepPath:                   return "timeStepPath";
    case ID_timeStepNames:                  return "timeStepNames";
    case ID_cycles:                         return "cycles";
    case ID_cyclesAreAccurate:              return "cyclesAreAccurate";
    case ID_times:                          return "times";
    case ID_timesAreAccurate:               return "timesAreAccurate";
    case ID_databaseName:                   return "databaseName";
    case ID_fileFormat:                     return "fileFormat";
    case ID_databaseComment:                return "databaseComment";
    case ID_exprList:                       return "exprList";
    case ID_meshes:                         return "meshes";
    case ID_subsets:                        return "subsets";
    case ID_scalars:                        return "scalars";
    case ID_vectors:                        return "vectors";
    case ID_tensors:                        return "tensors";
    case ID_symmTensors:                    return "symmTensors";
    case ID_arrays:                         return "arrays";
    case ID_materials:                      return "materials";
    case ID_species:                        return "species";
    case ID_curves:                         return "curves";
    case ID_labels:                         return "labels";
    case ID_defaultPlots:                   return "defaultPlots";
    case ID_isSimulation:                   return "isSimulation";
    case ID_simInfo:                        return "simInfo";
    case ID_suggestedDefaultSILRestriction: return "suggestedDefaultSILRestriction";
    case ID_replacementMask:                return "replacementMask";
    default:  return "invalid index";
    }
}

// ****************************************************************************
// Method: avtDatabaseMetaData::GetFieldType
//
// Purpose:
//   This method returns the type of a field given its index.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

AttributeGroup::FieldType
avtDatabaseMetaData::GetFieldType(int index) const
{
    switch (index)
    {
    case ID_hasTemporalExtents:             return FieldType_bool;
    case ID_minTemporalExtents:             return FieldType_double;
    case ID_maxTemporalExtents:             return FieldType_double;
    case ID_numStates:                      return FieldType_int;
    case ID_isVirtualDatabase:              return FieldType_bool;
    case ID_mustRepopulateOnStateChange:    return FieldType_bool;
    case ID_mustAlphabetizeVariables:       return FieldType_bool;
    case ID_formatCanDoDomainDecomposition: return FieldType_bool;
    case ID_formatCanDoMultires:            return FieldType_bool;
    case ID_useCatchAllMesh:                return FieldType_bool;
    case ID_timeStepPath:                   return FieldType_string;
    case ID_timeStepNames:                  return FieldType_stringVector;
    case ID_cycles:                         return FieldType_intVector;
    case ID_cyclesAreAccurate:              return FieldType_intVector;
    case ID_times:                          return FieldType_doubleVector;
    case ID_timesAreAccurate:               return FieldType_intVector;
    case ID_databaseName:                   return FieldType_string;
    case ID_fileFormat:                     return FieldType_string;
    case ID_databaseComment:                return FieldType_string;
    case ID_exprList:                       return FieldType_att;
    case ID_meshes:                         return FieldType_attVector;
    case ID_subsets:                        return FieldType_attVector;
    case ID_scalars:                        return FieldType_attVector;
    case ID_vectors:                        return FieldType_attVector;
    case ID_tensors:                        return FieldType_attVector;
    case ID_symmTensors:                    return FieldType_attVector;
    case ID_arrays:                         return FieldType_attVector;
    case ID_materials:                      return FieldType_attVector;
    case ID_species:                        return FieldType_attVector;
    case ID_curves:                         return FieldType_attVector;
    case ID_labels:                         return FieldType_attVector;
    case ID_defaultPlots:                   return FieldType_attVector;
    case ID_isSimulation:                   return FieldType_bool;
    case ID_simInfo:                        return FieldType_att;
    case ID_suggestedDefaultSILRestriction: return FieldType_stringVector;
    case ID_replacementMask:                return FieldType_int;
    default:  return FieldType_unknown;
    }
}

// ****************************************************************************
// Method: avtDatabaseMetaData::GetFieldTypeName
//
// Purpose:
//   This method returns the name of a field type given its index.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

std::string
avtDatabaseMetaData::GetFieldTypeName(int index) const
{
    switch (index)
    {
    case ID_hasTemporalExtents:             return "bool";
    case ID_minTemporalExtents:             return "double";
    case ID_maxTemporalExtents:             return "double";
    case ID_numStates:                      return "int";
    case ID_isVirtualDatabase:              return "bool";
    case ID_mustRepopulateOnStateChange:    return "bool";
    case ID_mustAlphabetizeVariables:       return "bool";
    case ID_formatCanDoDomainDecomposition: return "bool";
    case ID_formatCanDoMultires:            return "bool";
    case ID_useCatchAllMesh:                return "bool";
    case ID_timeStepPath:                   return "string";
    case ID_timeStepNames:                  return "stringVector";
    case ID_cycles:                         return "intVector";
    case ID_cyclesAreAccurate:              return "intVector";
    case ID_times:                          return "doubleVector";
    case ID_timesAreAccurate:               return "intVector";
    case ID_databaseName:                   return "string";
    case ID_fileFormat:                     return "string";
    case ID_databaseComment:                return "string";
    case ID_exprList:                       return "att";
    case ID_meshes:                         return "attVector";
    case ID_subsets:                        return "attVector";
    case ID_scalars:                        return "attVector";
    case ID_vectors:                        return "attVector";
    case ID_tensors:                        return "attVector";
    case ID_symmTensors:                    return "attVector";
    case ID_arrays:                         return "attVector";
    case ID_materials:                      return "attVector";
    case ID_species:                        return "attVector";
    case ID_curves:                         return "attVector";
    case ID_labels:                         return "attVector";
    case ID_defaultPlots:                   return "attVector";
    case ID_isSimulation:                   return "bool";
    case ID_simInfo:                        return "att";
    case ID_suggestedDefaultSILRestriction: return "stringVector";
    case ID_replacementMask:                return "int";
    default:  return "invalid index";
    }
}

// ****************************************************************************
// Method: avtDatabaseMetaData::FieldsEqual
//
// Purpose:
//   This method compares two fields and return true if they are equal.
//
// Note:       Autogenerated by xml2atts.
//
// Programmer: xml2atts
// Creation:   omitted
//
// Modifications:
//
// ****************************************************************************

bool
avtDatabaseMetaData::FieldsEqual(int index_, const AttributeGroup *rhs) const
{
    const avtDatabaseMetaData &obj = *((const avtDatabaseMetaData*)rhs);
    bool retval = false;
    switch (index_)
    {
    case ID_hasTemporalExtents:
        {  // new scope
        retval = (hasTemporalExtents == obj.hasTemporalExtents);
        }
        break;
    case ID_minTemporalExtents:
        {  // new scope
        retval = (minTemporalExtents == obj.minTemporalExtents);
        }
        break;
    case ID_maxTemporalExtents:
        {  // new scope
        retval = (maxTemporalExtents == obj.maxTemporalExtents);
        }
        break;
    case ID_numStates:
        {  // new scope
        retval = (numStates == obj.numStates);
        }
        break;
    case ID_isVirtualDatabase:
        {  // new scope
        retval = (isVirtualDatabase == obj.isVirtualDatabase);
        }
        break;
    case ID_mustRepopulateOnStateChange:
        {  // new scope
        retval = (mustRepopulateOnStateChange == obj.mustRepopulateOnStateChange);
        }
        break;
    case ID_mustAlphabetizeVariables:
        {  // new scope
        retval = (mustAlphabetizeVariables == obj.mustAlphabetizeVariables);
        }
        break;
    case ID_formatCanDoDomainDecomposition:
        {  // new scope
        retval = (formatCanDoDomainDecomposition == obj.formatCanDoDomainDecomposition);
        }
        break;
    case ID_formatCanDoMultires:
        {  // new scope
        retval = (formatCanDoMultires == obj.formatCanDoMultires);
        }
        break;
    case ID_useCatchAllMesh:
        {  // new scope
        retval = (useCatchAllMesh == obj.useCatchAllMesh);
        }
        break;
    case ID_timeStepPath:
        {  // new scope
        retval = (timeStepPath == obj.timeStepPath);
        }
        break;
    case ID_timeStepNames:
        {  // new scope
        retval = (timeStepNames == obj.timeStepNames);
        }
        break;
    case ID_cycles:
        {  // new scope
        retval = (cycles == obj.cycles);
        }
        break;
    case ID_cyclesAreAccurate:
        {  // new scope
        retval = (cyclesAreAccurate == obj.cyclesAreAccurate);
        }
        break;
    case ID_times:
        {  // new scope
        retval = (times == obj.times);
        }
        break;
    case ID_timesAreAccurate:
        {  // new scope
        retval = (timesAreAccurate == obj.timesAreAccurate);
        }
        break;
    case ID_databaseName:
        {  // new scope
        retval = (databaseName == obj.databaseName);
        }
        break;
    case ID_fileFormat:
        {  // new scope
        retval = (fileFormat == obj.fileFormat);
        }
        break;
    case ID_databaseComment:
        {  // new scope
        retval = (databaseComment == obj.databaseComment);
        }
        break;
    case ID_exprList:
        {  // new scope
        retval = (exprList == obj.exprList);
        }
        break;
    case ID_meshes:
        {  // new scope
        bool meshes_equal = (obj.meshes.size() == meshes.size());
        for(size_t i = 0; (i < meshes.size()) && meshes_equal; ++i)
        {
            // Make references to avtMeshMetaData from AttributeGroup *.
            const avtMeshMetaData &meshes1 = *((const avtMeshMetaData *)(meshes[i]));
            const avtMeshMetaData &meshes2 = *((const avtMeshMetaData *)(obj.meshes[i]));
            meshes_equal = (meshes1 == meshes2);
        }

        retval = meshes_equal;
        }
        break;
    case ID_subsets:
        {  // new scope
        bool subsets_equal = (obj.subsets.size() == subsets.size());
        for(size_t i = 0; (i < subsets.size()) && subsets_equal; ++i)
        {
            // Make references to avtSubsetsMetaData from AttributeGroup *.
            const avtSubsetsMetaData &subsets1 = *((const avtSubsetsMetaData *)(subsets[i]));
            const avtSubsetsMetaData &subsets2 = *((const avtSubsetsMetaData *)(obj.subsets[i]));
            subsets_equal = (subsets1 == subsets2);
        }

        retval = subsets_equal;
        }
        break;
    case ID_scalars:
        {  // new scope
        bool scalars_equal = (obj.scalars.size() == scalars.size());
        for(size_t i = 0; (i < scalars.size()) && scalars_equal; ++i)
        {
            // Make references to avtScalarMetaData from AttributeGroup *.
            const avtScalarMetaData &scalars1 = *((const avtScalarMetaData *)(scalars[i]));
            const avtScalarMetaData &scalars2 = *((const avtScalarMetaData *)(obj.scalars[i]));
            scalars_equal = (scalars1 == scalars2);
        }

        retval = scalars_equal;
        }
        break;
    case ID_vectors:
        {  // new scope
        bool vectors_equal = (obj.vectors.size() == vectors.size());
        for(size_t i = 0; (i < vectors.size()) && vectors_equal; ++i)
        {
            // Make references to avtVectorMetaData from AttributeGroup *.
            const avtVectorMetaData &vectors1 = *((const avtVectorMetaData *)(vectors[i]));
            const avtVectorMetaData &vectors2 = *((const avtVectorMetaData *)(obj.vectors[i]));
            vectors_equal = (vectors1 == vectors2);
        }

        retval = vectors_equal;
        }
        break;
    case ID_tensors:
        {  // new scope
        bool tensors_equal = (obj.tensors.size() == tensors.size());
        for(size_t i = 0; (i < tensors.size()) && tensors_equal; ++i)
        {
            // Make references to avtTensorMetaData from AttributeGroup *.
            const avtTensorMetaData &tensors1 = *((const avtTensorMetaData *)(tensors[i]));
            const avtTensorMetaData &tensors2 = *((const avtTensorMetaData *)(obj.tensors[i]));
            tensors_equal = (tensors1 == tensors2);
        }

        retval = tensors_equal;
        }
        break;
    case ID_symmTensors:
        {  // new scope
        bool symmTensors_equal = (obj.symmTensors.size() == symmTensors.size());
        for(size_t i = 0; (i < symmTensors.size()) && symmTensors_equal; ++i)
        {
            // Make references to avtSymmetricTensorMetaData from AttributeGroup *.
            const avtSymmetricTensorMetaData &symmTensors1 = *((const avtSymmetricTensorMetaData *)(symmTensors[i]));
            const avtSymmetricTensorMetaData &symmTensors2 = *((const avtSymmetricTensorMetaData *)(obj.symmTensors[i]));
            symmTensors_equal = (symmTensors1 == symmTensors2);
        }

        retval = symmTensors_equal;
        }
        break;
    case ID_arrays:
        {  // new scope
        bool arrays_equal = (obj.arrays.size() == arrays.size());
        for(size_t i = 0; (i < arrays.size()) && arrays_equal; ++i)
        {
            // Make references to avtArrayMetaData from AttributeGroup *.
            const avtArrayMetaData &arrays1 = *((const avtArrayMetaData *)(arrays[i]));
            const avtArrayMetaData &arrays2 = *((const avtArrayMetaData *)(obj.arrays[i]));
            arrays_equal = (arrays1 == arrays2);
        }

        retval = arrays_equal;
        }
        break;
    case ID_materials:
        {  // new scope
        bool materials_equal = (obj.materials.size() == materials.size());
        for(size_t i = 0; (i < materials.size()) && materials_equal; ++i)
        {
            // Make references to avtMaterialMetaData from AttributeGroup *.
            const avtMaterialMetaData &materials1 = *((const avtMaterialMetaData *)(materials[i]));
            const avtMaterialMetaData &materials2 = *((const avtMaterialMetaData *)(obj.materials[i]));
            materials_equal = (materials1 == materials2);
        }

        retval = materials_equal;
        }
        break;
    case ID_species:
        {  // new scope
        bool species_equal = (obj.species.size() == species.size());
        for(size_t i = 0; (i < species.size()) && species_equal; ++i)
        {
            // Make references to avtSpeciesMetaData from AttributeGroup *.
            const avtSpeciesMetaData &species1 = *((const avtSpeciesMetaData *)(species[i]));
            const avtSpeciesMetaData &species2 = *((const avtSpeciesMetaData *)(obj.species[i]));
            species_equal = (species1 == species2);
        }

        retval = species_equal;
        }
        break;
    case ID_curves:
        {  // new scope
        bool curves_equal = (obj.curves.size() == curves.size());
        for(size_t i = 0; (i < curves.size()) && curves_equal; ++i)
        {
            // Make references to avtCurveMetaData from AttributeGroup *.
            const avtCurveMetaData &curves1 = *((const avtCurveMetaData *)(curves[i]));
            const avtCurveMetaData &curves2 = *((const avtCurveMetaData *)(obj.curves[i]));
            curves_equal = (curves1 == curves2);
        }

        retval = curves_equal;
        }
        break;
    case ID_labels:
        {  // new scope
        bool labels_equal = (obj.labels.size() == labels.size());
        for(size_t i = 0; (i < labels.size()) && labels_equal; ++i)
        {
            // Make references to avtLabelMetaData from AttributeGroup *.
            const avtLabelMetaData &labels1 = *((const avtLabelMetaData *)(labels[i]));
            const avtLabelMetaData &labels2 = *((const avtLabelMetaData *)(obj.labels[i]));
            labels_equal = (labels1 == labels2);
        }

        retval = labels_equal;
        }
        break;
    case ID_defaultPlots:
        {  // new scope
        bool defaultPlots_equal = (obj.defaultPlots.size() == defaultPlots.size());
        for(size_t i = 0; (i < defaultPlots.size()) && defaultPlots_equal; ++i)
        {
            // Make references to avtDefaultPlotMetaData from AttributeGroup *.
            const avtDefaultPlotMetaData &defaultPlots1 = *((const avtDefaultPlotMetaData *)(defaultPlots[i]));
            const avtDefaultPlotMetaData &defaultPlots2 = *((const avtDefaultPlotMetaData *)(obj.defaultPlots[i]));
            defaultPlots_equal = (defaultPlots1 == defaultPlots2);
        }

        retval = defaultPlots_equal;
        }
        break;
    case ID_isSimulation:
        {  // new scope
        retval = (isSimulation == obj.isSimulation);
        }
        break;
    case ID_simInfo:
        {  // new scope
        retval = (simInfo == obj.simInfo);
        }
        break;
    case ID_suggestedDefaultSILRestriction:
        {  // new scope
        retval = (suggestedDefaultSILRestriction == obj.suggestedDefaultSILRestriction);
        }
        break;
    case ID_replacementMask:
        {  // new scope
        retval = (replacementMask == obj.replacementMask);
        }
        break;
    default: retval = false;
    }

    return retval;
}

///////////////////////////////////////////////////////////////////////////////
// User-defined methods.
///////////////////////////////////////////////////////////////////////////////

// ****************************************************************************
//  Method: avtDatabaseMetaData::SetTemporalExtents
//
//  Purpose:
//      Sets the minimum and maximum temporal extents.
//
//  Arguments:
//      min    The minimum temporal extents.
//      max    The maximum temporal extents.
//
//  Programmer: Hank Childs
//  Creation:   September 15, 2000
//
//  Modifications:
//
//    Hank Childs, Mon Mar 11 09:57:20 PST 2002
//    Changed type to double.
//
// ****************************************************************************

void
avtDatabaseMetaData::SetTemporalExtents(double min, double max)
{
    hasTemporalExtents = true;
    minTemporalExtents = min;
    maxTemporalExtents = max;
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::SetCycle
//
//  Purpose:
//      Sets a cycle for a specific timestep.
//
//  Arguments:
//      ts       The timestep.
//      c        The cycle number.
//
//  Programmer:  Hank Childs
//  Creation:    March 11, 2002
// ****************************************************************************

void
avtDatabaseMetaData::SetCycle(int ts, int c)
{
    if(ts >= 0 && ts < (int)cyclesAreAccurate.size())
    {
        cycles[ts] = c;
        cyclesAreAccurate[ts] = true;
    }
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::SetCycleIsAccurate
//
//  Purpose:
//      Sets a boolean indicating whether a cycle number is accurate.
//
//  Arguments:
//      b       A boolean indicating whether a cycle is accurate.
//      ts      The timestep b corresponds to.
//
//  Programmer: Hank Childs
//  Creation:   March 11, 2002
//
// ****************************************************************************

void
avtDatabaseMetaData::SetCycleIsAccurate(bool b, int ts)
{
    if(ts >= 0 && ts < (int)cyclesAreAccurate.size())
        cyclesAreAccurate[ts] = (b ? 1 : 0);
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::SetCyclesAreAccurate
//
//  Purpose:
//      Sets a boolean indicating whether the cycle numbers are accurate.
//
//  Arguments:
//      b       A boolean indicating whether the cycle std::vector is accurate.
//
//  Programmer: Hank Childs
//  Creation:   March 11, 2002
//
// ****************************************************************************

void
avtDatabaseMetaData::SetCyclesAreAccurate(bool b)
{
    for (size_t i = 0 ; i < cyclesAreAccurate.size() ; i++)
    {
        cyclesAreAccurate[i] = (b ? 1 : 0);
    }
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::IsCycleAccurate
//
//  Purpose:
//      Gets whether a single cycle is accurate.
//
//  Arguments:
//      ts       A timestep index.
//
//  Returns:     true if the cycle is accurate, false otherwise.
//
//  Programmer:  Hank Childs
//  Creation:    March 11, 2002
//
// ****************************************************************************

bool
avtDatabaseMetaData::IsCycleAccurate(int ts) const
{
    if(ts >= 0 && ts < (int)cyclesAreAccurate.size())
        return (cyclesAreAccurate[ts] != 0 ? true : false);
    return false;
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::AreAllCyclesAccurateAndValid
//
//  Purpose: Convenience method for checking if ALL cycles are accurate and
//  valid (are monotone increasing and there are numStates of them). If the
//  caller doesn't know the expected number of states, it can pass void to
//  use the numStates known in avtDatabaseMetaData
//
//  Programmer:  Mark C. Miller
//  Creation:    March 16, 2005
//
//  Modifications:
//    Mark C. Miller, Tue Mar  6 23:40:10 PST 2007
//    Corrected logic for monotone increasing
//
// ****************************************************************************

bool
avtDatabaseMetaData::AreAllCyclesAccurateAndValid(int expectedNumStates) const
{
    int useNumStates = expectedNumStates == -1 ? numStates : expectedNumStates;

    if ((int)cyclesAreAccurate.size() != useNumStates)
        return false;

    if (cyclesAreAccurate.size() != cycles.size())
        return false;

    for (int i = 0 ; i < useNumStates; i++)
    {
        if (cyclesAreAccurate[i] == 0)
            return false;
        if ((i > 0) && !((cycles[i-1] <= cycles[i])))
            return false;
    }
    return true;
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::SetTime
//
//  Purpose:
//      Sets a time for a specific timestep.
//
//  Arguments:
//      ts       The timestep.
//      t        The time.
//
//  Programmer:  Hank Childs
//  Creation:    March 11, 2002
// ****************************************************************************

void
avtDatabaseMetaData::SetTime(int ts, double t)
{
    if(ts >= 0 && ts < (int)timesAreAccurate.size())
    {
        times[ts] = t;
        timesAreAccurate[ts] = true;
    }
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::SetTimeIsAccurate
//
//  Purpose:
//      Sets a boolean indicating whether a specific timestep is accurate.
//
//  Arguments:
//      b       A boolean indicating whether a time is accurate.
//      ts      The timestep b corresponds to.
//
//  Programmer: Hank Childs
//  Creation:   March 11, 2002
//
// ****************************************************************************

void
avtDatabaseMetaData::SetTimeIsAccurate(bool b, int ts)
{
    if(ts >= 0 && ts < (int)timesAreAccurate.size())
        timesAreAccurate[ts] = (b ? 1 : 0);
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::SetTimesAreAccurate
//
//  Purpose:
//      Sets a boolean indicating whether the times are accurate.
//
//  Arguments:
//      b       A boolean indicating whether the times std::vector is accurate.
//
//  Programmer: Hank Childs
//  Creation:   March 11, 2002
//
// ****************************************************************************

void
avtDatabaseMetaData::SetTimesAreAccurate(bool b)
{
    for (size_t i = 0 ; i < timesAreAccurate.size() ; i++)
    {
        timesAreAccurate[i] = (b ? 1 : 0);
    }
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::IsTimeAccurate
//
//  Purpose:
//      Gets whether a single time is accurate.
//
//  Arguments:
//      ts       A timestep index.
//
//  Returns:     true if the time is accurate, false otherwise.
//
//  Programmer:  Hank Childs
//  Creation:    March 11, 2002
//
// ****************************************************************************

bool
avtDatabaseMetaData::IsTimeAccurate(int ts) const
{
    if(ts >= 0 && ts < (int)timesAreAccurate.size())
        return timesAreAccurate[ts] != 0;
    return false;
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::AreAllTimesAccurateAndValid
//
//  Purpose: Convenience method to check if all times are accurate and
//  monotone increasing. If the caller doesn't know the expected number of
//  states, it can pass void (it will default to -1) and the numStates in
//  avtDatabaseMetaData will be used
//
//  Programmer:  Mark C. Miller
//  Creation:    March 16, 2005
//
//  Modifications:
//    Mark C. Miller, Tue Mar  6 23:40:10 PST 2007
//    Corrected logic for monotone increasing
// ****************************************************************************

bool
avtDatabaseMetaData::AreAllTimesAccurateAndValid(int expectedNumStates) const
{
    int useNumStates = expectedNumStates == -1 ? numStates : expectedNumStates;

    if ((int)timesAreAccurate.size() != useNumStates)
        return false;

    if (timesAreAccurate.size() != times.size())
        return false;

    for (int i = 0 ; i < useNumStates; i++)
    {
        if (timesAreAccurate[i] == 0)
            return false;
        if ((i > 0) && !((times[i-1] <= times[i])))
            return false;
    }
    return true;
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::ReplaceForbiddenCharacters
//
//  Purpose:
//      Goes to each of the meta-data objects and replaces characters that
//      are forbidden with a replacement string.
//
//  Programmer: Hank Childs
//  Creation:   February 14, 2005
//
//  Modifications:
//    Brad Whitlock, Fri Apr 1 15:40:29 PST 2005
//    Added labels.
//
//    Hank Childs, Sun Apr 24 10:58:09 PDT 2005
//    Add better support for meshes that are renamed.
//
//    Hank Childs, Tue Jul 19 13:24:19 PDT 2005
//    Added support for arrays.
//
//    Dave Pugmire, Thu Mar  4 10:27:17 EST 2010
//    Added support for curves.
//
//    Brad Whitlock, Tue May 11 14:50:46 PDT 2010
//    Check replacementMask before doing character replacement.
//
//    Mark C. Miller, Thu Sep 15 13:03:15 PDT 2016
//    Moved code setting up forbidden characters and replacement strings from
//    avtGenericDatabase to here. Adjusted interfaces to used C char*'s
//    instead of C++ strings.
// ****************************************************************************

static char const *forbiddenVarNameChars = "\n\t@#:[]<>(){}";

static char const * const replacementVarNameStrs[13] = {
    "_nl_",     // \n
    "_tab_",    // \t
    "_at_",     // @
    "_number_", // #
    "_colon_",  // :
    "_lb_",     // [
    "_rb_",     // ]
    "_la_",     // <
    "_ra_",     // >
    "_lp_",     // (
    "_rp_",     // )
    "_lc_",     // {
    "_rc_"      // }
};

static bool IsForbidden(std::string const &origName, std::string &newName,
                 char const *badChars, char const * const *newStr)
{
    //
    // Note: this is rather unefficiently implemented.  It is expected that
    // this won't be called often.  If it is, then we should re-implement this
    // so "badChars" can be looked up in constant time (presumably using
    // some sort of hash based on the ASCII index of the character).
    //
    bool shouldReplace = false;
    char new_name[1024];
    const char *orig_name = origName.c_str();
    size_t len = strlen(orig_name);
    size_t cur = 0;
    for (size_t i = 0 ; i < len ; i++)
    {
        bool hadBadChar = false;
        for (size_t j = 0 ; j < strlen(badChars) ; j++)
        {
            if (orig_name[i] == badChars[j])
            {
                hadBadChar = true;
                const char *replacement = newStr[j];
                size_t len2 = strlen(replacement);
                for (size_t k = 0 ; k < len2 ; k++)
                {
                    new_name[cur++] = replacement[k];
                }
            }
        }
        if (hadBadChar)
            shouldReplace = true;
        else
            new_name[cur++] = orig_name[i];
    }
    new_name[cur++] = '\0';
    newName = new_name;

    return shouldReplace;
}

void
avtDatabaseMetaData::ReplaceForbiddenCharacters(void)
{
    int  i;

    std::string replacementName;

    if((replacementMask & VAR_CATEGORY_MESH) > 0)
    {
        for (i = 0 ; i < GetNumMeshes() ; i++)
        {
            if (GetMeshes(i).originalName == "")
                GetMeshes(i).originalName = GetMeshes(i).name;
            if (IsForbidden(GetMeshes(i).originalName, replacementName,
                            forbiddenVarNameChars, replacementVarNameStrs))
            {
                char msg[1024];
                snprintf(msg, 1024, "The database contains an object named \"%s\""
                                 ", which contains characters not supported by "
                                 "VisIt.  VisIt is renaming it to \"%s\"",
                                 GetMeshes(i).originalName.c_str(),
                                 replacementName.c_str());
                IssueWarning(msg);
                GetMeshes(i).name = replacementName;
            }
        }
    }

    if((replacementMask & VAR_CATEGORY_SCALAR) > 0)
    {
        for (i = 0 ; i < GetNumScalars() ; i++)
        {
            if (GetScalars(i).originalName == "")
                GetScalars(i).originalName = GetScalars(i).name;
            if (IsForbidden(GetScalars(i).originalName, replacementName,
                            forbiddenVarNameChars, replacementVarNameStrs))
            {
                char msg[1024];
                snprintf(msg, 1024, "The database contains an object named \"%s\""
                                 ", which contains characters not supported by "
                                 "VisIt.  VisIt is renaming it to \"%s\"",
                                 GetScalars(i).originalName.c_str(),
                                 replacementName.c_str());
                IssueWarning(msg);
                GetScalars(i).name = replacementName;
            }
            if (IsForbidden(GetScalars(i).meshName, replacementName,
                            forbiddenVarNameChars, replacementVarNameStrs))
                GetScalars(i).meshName = replacementName;
        }
    }

    if((replacementMask & VAR_CATEGORY_VECTOR) > 0)
    {
        for (i = 0 ; i < GetNumVectors() ; i++)
        {
            if (GetVectors(i).originalName == "")
                GetVectors(i).originalName = GetVectors(i).name;
            if (IsForbidden(GetVectors(i).originalName, replacementName,
                            forbiddenVarNameChars, replacementVarNameStrs))
            {
                char msg[1024];
                snprintf(msg, 1024, "The database contains an object named \"%s\""
                                 ", which contains characters not supported by "
                                 "VisIt.  VisIt is renaming it to \"%s\"",
                                 GetVectors(i).originalName.c_str(),
                                 replacementName.c_str());
                IssueWarning(msg);
                GetVectors(i).name = replacementName;
            }
            if (IsForbidden(GetVectors(i).meshName, replacementName,
                            forbiddenVarNameChars, replacementVarNameStrs))
                GetVectors(i).meshName = replacementName;
        }
    }

    if((replacementMask & VAR_CATEGORY_TENSOR) > 0)
    {
        for (i = 0 ; i < GetNumTensors() ; i++)
        {
            if (GetTensors(i).originalName == "")
                GetTensors(i).originalName = GetTensors(i).name;
            if (IsForbidden(GetTensors(i).originalName, replacementName,
                            forbiddenVarNameChars, replacementVarNameStrs))
            {
                char msg[1024];
                snprintf(msg, 1024, "The database contains an object named \"%s\""
                                 ", which contains characters not supported by "
                                 "VisIt.  VisIt is renaming it to \"%s\"",
                                 GetTensors(i).originalName.c_str(),
                                 replacementName.c_str());
                IssueWarning(msg);
                GetTensors(i).name = replacementName;
            }
            if (IsForbidden(GetTensors(i).meshName, replacementName,
                            forbiddenVarNameChars, replacementVarNameStrs))
                GetTensors(i).meshName = replacementName;
        }
    }

    if((replacementMask & VAR_CATEGORY_SYMMETRIC_TENSOR) > 0)
    {
        for (i = 0 ; i < GetNumSymmTensors() ; i++)
        {
            if (GetSymmTensors(i).originalName == "")
                GetSymmTensors(i).originalName = GetSymmTensors(i).name;
            if (IsForbidden(GetSymmTensors(i).originalName, replacementName,
                            forbiddenVarNameChars, replacementVarNameStrs))
            {
                char msg[1024];
                snprintf(msg, 1024, "The database contains an object named \"%s\""
                                 ", which contains characters not supported by "
                                 "VisIt.  VisIt is renaming it to \"%s\"",
                                 GetSymmTensors(i).originalName.c_str(),
                                 replacementName.c_str());
                IssueWarning(msg);
                GetSymmTensors(i).name = replacementName;
            }
            if (IsForbidden(GetSymmTensors(i).meshName, replacementName,
                            forbiddenVarNameChars, replacementVarNameStrs))
                GetSymmTensors(i).meshName = replacementName;
        }
    }

    if((replacementMask & VAR_CATEGORY_ARRAY) > 0)
    {
        for (i = 0 ; i < GetNumArrays() ; i++)
        {
            if (GetArrays(i).originalName == "")
                GetArrays(i).originalName = GetArrays(i).name;
            if (IsForbidden(GetArrays(i).originalName, replacementName,
                            forbiddenVarNameChars, replacementVarNameStrs))
            {
                char msg[1024];
                snprintf(msg, 1024, "The database contains an object named \"%s\""
                                 ", which contains characters not supported by "
                                 "VisIt.  VisIt is renaming it to \"%s\"",
                                 GetArrays(i).originalName.c_str(),
                                 replacementName.c_str());
                IssueWarning(msg);
                GetArrays(i).name = replacementName;
            }
            if (IsForbidden(GetArrays(i).meshName, replacementName,
                            forbiddenVarNameChars, replacementVarNameStrs))
                GetArrays(i).meshName = replacementName;
        }
    }

    if((replacementMask & VAR_CATEGORY_MATERIAL) > 0)
    {
        for (i = 0 ; i < GetNumMaterials() ; i++)
        {
            if (GetMaterials(i).originalName == "")
                GetMaterials(i).originalName = GetMaterials(i).name;
            if (IsForbidden(GetMaterials(i).originalName, replacementName,
                            forbiddenVarNameChars, replacementVarNameStrs))
            {
                char msg[1024];
                snprintf(msg, 1024, "The database contains an object named \"%s\""
                                 ", which contains characters not supported by "
                                 "VisIt.  VisIt is renaming it to \"%s\"",
                                 GetMaterials(i).originalName.c_str(),
                                 replacementName.c_str());
                IssueWarning(msg);
                GetMaterials(i).name = replacementName;
            }
            if (IsForbidden(GetMaterials(i).meshName, replacementName,
                            forbiddenVarNameChars, replacementVarNameStrs))
                GetMaterials(i).meshName = replacementName;
        }
    }

    if((replacementMask & VAR_CATEGORY_CURVE) > 0)
    {
        for (i = 0; i < GetNumCurves(); i++)
        {
            if (GetCurves(i).originalName == "")
                GetCurves(i).originalName = GetCurves(i).name;
            if (IsForbidden(GetCurves(i).originalName, replacementName,
                            forbiddenVarNameChars, replacementVarNameStrs))
            {
                char msg[1024];
                snprintf(msg, 1024, "The database contains an object named \"%s\""
                                 ", which contains characters not supported by "
                                 "VisIt.  VisIt is renaming it to \"%s\"",
                                 GetCurves(i).originalName.c_str(),
                                 replacementName.c_str());
                IssueWarning(msg);
                GetCurves(i).name = replacementName;
            }
        }
    }

    if((replacementMask & VAR_CATEGORY_LABEL) > 0)
    {
        for (i = 0 ; i < GetNumLabels() ; i++)
        {
            if (GetLabels(i).originalName == "")
                GetLabels(i).originalName = GetLabels(i).name;
            if (IsForbidden(GetLabels(i).originalName, replacementName,
                            forbiddenVarNameChars, replacementVarNameStrs))
            {
                char msg[1024];
                snprintf(msg, 1024, "The database contains an object named \"%s\""
                                 ", which contains characters not supported by "
                                 "VisIt.  VisIt is renaming it to \"%s\"",
                                 GetLabels(i).originalName.c_str(),
                                 replacementName.c_str());
                IssueWarning(msg);
                GetLabels(i).name = replacementName;
            }
            if (IsForbidden(GetLabels(i).meshName, replacementName,
                            forbiddenVarNameChars, replacementVarNameStrs))
                GetLabels(i).meshName = replacementName;
        }
    }
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::Add
//
//  Arguments:
//      mmd    A mesh meta data object.
//
//  Programmer: Hank Childs
//  Creation:   August 28, 2000
//
//  Modifications:
//
//    Mark C. Miller, Tue Sep 28 19:57:42 PDT 2004
//    Added code to make sure num blocks is 1 if
//    formatCanDoDomainDecomposition is true
//
//    Mark C. Miller, Mon Jul 18 13:41:13 PDT 2005
//    Added code to assure topological dimension is zero if its a point
//    mesh. VisIt has subtle problems with pipeline if it is not.
//
//    Jeremy Meredith, Tue Aug  2 10:45:01 PDT 2005
//    Changed the new m.m.d. for point meshes to avoid using a temporary.
//
//    Brad Whitlock, Tue Nov 27 15:51:36 PST 2007
//    Turn topdim==0 unstructured meshes into point meshes.
//
// ****************************************************************************

void
avtDatabaseMetaData::Add(avtMeshMetaData *mmd)
{
    if (formatCanDoDomainDecomposition && mmd->numBlocks != 1)
    {
        EXCEPTION1(ImproperUseException, "Cannot deal with meshes having "
            "other than a single block in formats that do their own domain "
            "decomposition.");
    }
    if (mmd->meshType == AVT_POINT_MESH && mmd->topologicalDimension != 0)
    {
        // we shouldn't modify the caller's object, so make a copy
        avtMeshMetaData *tmpmmd = new avtMeshMetaData(*mmd);
        tmpmmd->topologicalDimension = 0;
        meshes.push_back(tmpmmd);
    }
    else if (mmd->meshType == AVT_UNSTRUCTURED_MESH && mmd->topologicalDimension == 0)
    {
        mmd->meshType = AVT_POINT_MESH;
        meshes.push_back(mmd);
    }
    else
    {
        meshes.push_back(mmd);
    }
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::Add
//
//  Arguments:
//      smd    A scalar meta data object.
//
//  Programmer: Hank Childs
//  Creation:   August 28, 2000
//
// ****************************************************************************

void
avtDatabaseMetaData::Add(avtScalarMetaData *smd)
{
    scalars.push_back(smd);
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::Add
//
//  Arguments:
//      vmd    A vector meta data object.
//
//  Programmer: Hank Childs
//  Creation:   August 28, 2000
//
// ****************************************************************************

void
avtDatabaseMetaData::Add(avtVectorMetaData *vmd)
{
    vectors.push_back(vmd);
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::Add
//
//  Arguments:
//      tmd    A tensor meta data object.
//
//  Programmer: Hank Childs
//  Creation:   September 20, 2003
//
// ****************************************************************************

void
avtDatabaseMetaData::Add(avtTensorMetaData *tmd)
{
    tensors.push_back(tmd);
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::Add
//
//  Arguments:
//     stmd   A symmetric tensor meta data object.
//
//  Programmer: Hank Childs
//  Creation:   September 20, 2003
//
// ****************************************************************************

void
avtDatabaseMetaData::Add(avtSymmetricTensorMetaData *stmd)
{
    symmTensors.push_back(stmd);
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::Add
//
//  Arguments:
//      tmd    An array meta data object.
//
//  Programmer: Hank Childs
//  Creation:   July 19, 2005
//
// ****************************************************************************

void
avtDatabaseMetaData::Add(avtArrayMetaData *tmd)
{
    arrays.push_back(tmd);
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::Add
//
//  Arguments:
//      mmd    A material meta data object.
//
//  Programmer: Hank Childs
//  Creation:   August 28, 2000
//
// ****************************************************************************

void
avtDatabaseMetaData::Add(avtMaterialMetaData *mmd)
{
    materials.push_back(mmd);
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::Add
//
//  Arguments:
//      smd    A species meta data object.
//
//  Programmer: Hank Childs
//  Creation:   August 28, 2000
//
// ****************************************************************************

void
avtDatabaseMetaData::Add(avtSpeciesMetaData *smd)
{
    species.push_back(smd);
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::Add
//
//  Arguments:
//      cmd    A curve meta data object.
//
//  Programmer: Hank Childs
//  Creation:   August 1, 2003
//
// ****************************************************************************

void
avtDatabaseMetaData::Add(avtCurveMetaData *cmd)
{
    curves.push_back(cmd);
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::Add
//
//  Arguments:
//      smd    A Label meta data object.
//
//  Programmer: Brad Whitlock
//  Creation:   Fri Apr 1 15:26:41 PST 2005
//
// ****************************************************************************

void
avtDatabaseMetaData::Add(avtLabelMetaData *lmd)
{
    labels.push_back(lmd);
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::Add
//
//  Arguments:
//      pmd    A default plot meta data object.
//
//  Programmer: Walter Herrera
//  Creation:   Septemver 04, 2003
//
// ****************************************************************************

void
avtDatabaseMetaData::Add(avtDefaultPlotMetaData *pmd)
{
    defaultPlots.push_back(pmd);
}

// *******************************************************************
// Method: avtDatabaseMetaData::GetMesh
//
// Purpose:
//     This returns the metadata for the nth mesh in the file.
//
// Arguments:
//     n  :  the index into the array
//
// Programmer: Jeremy Meredith
// Creation:   September  1, 2000
//
// Modifications:
//
//   Hank Childs, Thu Mar 30 12:11:43 PST 2006
//   Add some checking for indices.
//
// *******************************************************************

const avtMeshMetaData *
avtDatabaseMetaData::GetMesh(int n) const
{
    if (n < 0 || n >= GetNumMeshes())
        EXCEPTION2(BadIndexException, n, GetNumMeshes());

    return (const avtMeshMetaData *)meshes[n];
}

// *******************************************************************
// Method: avtDatabaseMetaData::GetMesh
//
// Purpose:
//     This returns the metadata for the mesh in the file whose name is n.
//
// Arguments:
//     n  :  the name of the mesh object
//
// Programmer: Jeremy Meredith
// Creation:   September  1, 2000
//
// Modifications:
//
// *******************************************************************

const avtMeshMetaData *
avtDatabaseMetaData::GetMesh(const std::string &n) const
{
    for (int i=0; i<GetNumMeshes(); i++)
        if (VariableNamesEqual(GetMesh(i)->name, n))
            return GetMesh(i);
    return NULL;
}

// *******************************************************************
// Method: avtDatabaseMetaData::GetScalar
//
// Purpose:
//     This returns the metadata for the nth scalar in the file.
//
// Arguments:
//     n  :  the index into the array
//
// Programmer: Jeremy Meredith
// Creation:   September  1, 2000
//
// Modifications:
//
//   Hank Childs, Thu Mar 30 12:11:43 PST 2006
//   Add some checking for indices.
//
// *******************************************************************

const avtScalarMetaData *
avtDatabaseMetaData::GetScalar(int n) const
{
    if (n < 0 || n >= GetNumScalars())
        EXCEPTION2(BadIndexException, n, GetNumScalars());

    return (const avtScalarMetaData *)scalars[n];
}

// *******************************************************************
// Method: avtDatabaseMetaData::GetScalar
//
// Purpose:
//     This returns the metadata for the scalar in the file whose name is n.
//
// Arguments:
//     n  :  the name of the scalar object
//
// Programmer: Jeremy Meredith
// Creation:   September  1, 2000
//
// Modifications:
//
// *******************************************************************

const avtScalarMetaData *
avtDatabaseMetaData::GetScalar(const std::string &n) const
{
    for (int i=0; i<GetNumScalars(); i++)
        if (VariableNamesEqual(GetScalar(i)->name, n))
            return GetScalar(i);
    return NULL;
}

// *******************************************************************
// Method: avtDatabaseMetaData::GetVector
//
// Purpose:
//     This returns the metadata for the nth vector in the file.
//
// Arguments:
//     n  :  the index into the array
//
// Programmer: Jeremy Meredith
// Creation:   September  1, 2000
//
// Modifications:
//
//   Hank Childs, Thu Mar 30 12:11:43 PST 2006
//   Add some checking for indices.
//
// *******************************************************************

const avtVectorMetaData *
avtDatabaseMetaData::GetVector(int n) const
{
    if (n < 0 || n >= GetNumVectors())
        EXCEPTION2(BadIndexException, n, GetNumVectors());

    return (const avtVectorMetaData *)vectors[n];
}

// *******************************************************************
// Method: avtDatabaseMetaData::GetVector
//
// Purpose:
//     This returns the metadata for the vector in the file whose name is n.
//
// Arguments:
//     n  :  the name of the vector object
//
// Programmer: Jeremy Meredith
// Creation:   September  1, 2000
//
// Modifications:
//
// *******************************************************************

const avtVectorMetaData *
avtDatabaseMetaData::GetVector(const std::string &n) const
{
    for (int i=0; i<GetNumVectors(); i++)
        if (VariableNamesEqual(GetVector(i)->name, n))
            return GetVector(i);
    return NULL;
}

// ****************************************************************************
// Method: avtDatabaseMetaData::GetTensor
//
// Purpose:
//     This returns the metadata for the nth tensor in the file.
//
// Arguments:
//     n  :  the index into the array
//
// Programmer: Hank Childs
// Creation:   September 20, 2003
//
//   Hank Childs, Thu Mar 30 12:11:43 PST 2006
//   Add some checking for indices.
//
// ****************************************************************************

const avtTensorMetaData *
avtDatabaseMetaData::GetTensor(int n) const
{
    if (n < 0 || n >= GetNumTensors())
        EXCEPTION2(BadIndexException, n, GetNumTensors());

    return (const avtTensorMetaData *)tensors[n];
}

// ****************************************************************************
// Method: avtDatabaseMetaData::GetTensor
//
// Purpose:
//     This returns the metadata for the tensor in the file whose name is n.
//
// Arguments:
//     n  :  the name of the tensor object
//
// Programmer: Hank Childs
// Creation:   September 20, 2003
//
// ****************************************************************************

const avtTensorMetaData *
avtDatabaseMetaData::GetTensor(const std::string &n) const
{
    for (int i=0; i<GetNumTensors(); i++)
        if (VariableNamesEqual(GetTensors(i).name, n))
            return GetTensor(i);
    return NULL;
}

// ****************************************************************************
// Method: avtDatabaseMetaData::GetSymmTensor
//
// Purpose:
//     This returns the metadata for the nth symmetric tensor in the file.
//
// Arguments:
//     n  :  the index into the array
//
// Programmer: Hank Childs
// Creation:   September 20, 2003
//
// Modifications:
//
//   Hank Childs, Thu Mar 30 12:11:43 PST 2006
//   Add some checking for indices.
//
// ****************************************************************************

const avtSymmetricTensorMetaData *
avtDatabaseMetaData::GetSymmTensor(int n) const
{
    if (n < 0 || n >= GetNumSymmTensors())
        EXCEPTION2(BadIndexException, n, GetNumSymmTensors());

    return (const avtSymmetricTensorMetaData *)symmTensors[n];
}

// ****************************************************************************
// Method: avtDatabaseMetaData::GetSymmTensor
//
// Purpose:
//     This returns the metadata for the symmetric tensor in the file whose
//     name is n.
//
// Arguments:
//     n  :  the name of the tensor object
//
// Programmer: Hank Childs
// Creation:   September 20, 2003
//
// ****************************************************************************

const avtSymmetricTensorMetaData *
avtDatabaseMetaData::GetSymmTensor(const std::string &n) const
{
    for (int i=0; i<GetNumSymmTensors(); i++)
        if (VariableNamesEqual(GetSymmTensors(i).name, n))
            return GetSymmTensor(i);
    return NULL;
}

// ****************************************************************************
// Method: avtDatabaseMetaData::GetArray
//
// Purpose:
//     This returns the metadata for the nth arrays in the file.
//
// Arguments:
//     n  :  the index into the array
//
// Programmer: Hank Childs
// Creation:   July 19, 2005
//
// Modifications:
//
//   Hank Childs, Thu Mar 30 12:11:43 PST 2006
//   Add some checking for indices.
//
// ****************************************************************************

const avtArrayMetaData *
avtDatabaseMetaData::GetArray(int n) const
{
    if (n < 0 || n >= GetNumArrays())
        EXCEPTION2(BadIndexException, n, GetNumArrays());

    return (const avtArrayMetaData *)arrays[n];
}

// ****************************************************************************
// Method: avtDatabaseMetaData::GetArray
//
// Purpose:
//     This returns the metadata for the arrays in the file whose name is n.
//
// Arguments:
//     n  :  the name of the arrays object
//
// Programmer: Hank Childs
// Creation:   July 19, 2005
//
// ****************************************************************************

const avtArrayMetaData *
avtDatabaseMetaData::GetArray(const std::string &n) const
{
    for (int i=0; i<GetNumArrays(); i++)
        if (VariableNamesEqual(GetArrays(i).name, n))
            return GetArray(i);
    return NULL;
}

// *******************************************************************
// Method: avtDatabaseMetaData::GetMaterial
//
// Purpose:
//     This returns the metadata for the nth material in the file.
//
// Arguments:
//     n  :  the index into the array
//
// Programmer: Jeremy Meredith
// Creation:   September  1, 2000
//
// Modifications:
//
//   Hank Childs, Thu Mar 30 12:11:43 PST 2006
//   Add some checking for indices.
//
// *******************************************************************

const avtMaterialMetaData *
avtDatabaseMetaData::GetMaterial(int n) const
{
    if (n < 0 || n >= GetNumMaterials())
        EXCEPTION2(BadIndexException, n, GetNumMaterials());

    return (const avtMaterialMetaData *)materials[n];
}

// *******************************************************************
// Method: avtDatabaseMetaData::GetMaterial
//
// Purpose:
//     This returns the metadata for the material in the file whose name is n.
//
// Arguments:
//     n  :  the name of the material object
//
// Programmer: Jeremy Meredith
// Creation:   September  1, 2000
//
// Modifications:
//   Kathleen Bonnell, Thu Sep  5 13:53:15 PDT 2002
//   Call ParseCompoundForVar, in case the variable is compound.
// *******************************************************************

const avtMaterialMetaData *
avtDatabaseMetaData::GetMaterial(const std::string &n) const
{
    std::string n2;
    const_cast<avtDatabaseMetaData*>(this)->ParseCompoundForVar(n, n2);
    for (int i=0; i<GetNumMaterials(); i++)
        if (VariableNamesEqual(GetMaterials(i).name, n2))
            return GetMaterial(i);
    return NULL;
}

// *******************************************************************
// Method: avtDatabaseMetaData::GetSpecies
//
// Purpose:
//     This returns the metadata for the species in the file whose name is n.
//
// Arguments:
//     n  :  the name of the species object
//
// Programmer: Jeremy Meredith
// Creation:   September  1, 2000
//
// Modifications:
//
// *******************************************************************

const avtSpeciesMetaData *
avtDatabaseMetaData::GetSpecies(const std::string &n) const
{
    for (int i=0; i<GetNumSpecies(); i++)
        if (VariableNamesEqual(GetSpecies(i).name, n))
            return (const avtSpeciesMetaData *)species[i];
    return NULL;
}

// *******************************************************************
// Method: avtDatabaseMetaData::GetCurve
//
// Purpose:
//     This returns the metadata for the nth curve in the file.
//
// Arguments:
//     n  :  the index into the array
//
// Programmer: Hank Childs
// Creation:   August 1, 2003
//
// Modifications:
//
//   Hank Childs, Thu Mar 30 12:11:43 PST 2006
//   Add some checking for indices.
//
// *******************************************************************

const avtCurveMetaData *
avtDatabaseMetaData::GetCurve(int n) const
{
    if (n < 0 || n >= GetNumCurves())
        EXCEPTION2(BadIndexException, n, GetNumCurves());

    return (const avtCurveMetaData *)curves[n];
}

// *******************************************************************
// Method: avtDatabaseMetaData::GetCurve
//
// Purpose:
//     This returns the metadata for the curve in the file whose name
//     is n.
//
// Arguments:
//     n  :  the name of the curve object
//
// Programmer: Hank Childs
// Creation:   August  1, 2003
//
// Modifications:
//
// *******************************************************************

const avtCurveMetaData *
avtDatabaseMetaData::GetCurve(const std::string &n) const
{
    for (int i=0; i<GetNumCurves(); i++)
        if (VariableNamesEqual(GetCurves(i).name, n))
            return GetCurve(i);
    return NULL;
}

// *******************************************************************
// Method: avtDatabaseMetaData::GetLabel
//
// Purpose:
//     This returns the metadata for the nth label in the file.
//
// Arguments:
//     n  :  the index into the array
//
// Programmer: Brad Whitlock
// Creation:   Fri Apr 1 15:37:40 PST 2005
//
// Modifications:
//
//   Hank Childs, Thu Mar 30 12:11:43 PST 2006
//   Add some checking for indices.
//
// *******************************************************************

const avtLabelMetaData *
avtDatabaseMetaData::GetLabel(int n) const
{
    if (n < 0 || n >= GetNumLabels())
        EXCEPTION2(BadIndexException, n, GetNumLabels());

    return (const avtLabelMetaData *)labels[n];
}

// *******************************************************************
// Method: avtDatabaseMetaData::GetLabel
//
// Purpose:
//     This returns the metadata for the label in the file whose name is n.
//
// Arguments:
//     n  :  the name of the label object
//
// Programmer: Brad Whitlock
// Creation:   Fri Apr 1 15:37:59 PST 2005
//
// Modifications:
//
// *******************************************************************

const avtLabelMetaData *
avtDatabaseMetaData::GetLabel(const std::string &n) const
{
    for (int i=0; i<GetNumLabels(); i++)
        if (VariableNamesEqual(GetLabels(i).name, n))
            return GetLabel(i);
    return NULL;
}

// *******************************************************************
// Method: avtDatabaseMetaData::GetDefaultPlot
//
// Purpose:
//     This returns the metadata for the nth default plot in the file.
//
// Arguments:
//     n  :  the index into the array
//
// Programmer: Walter Herrera
// Creation:   September 04, 2003
//
// Modifications:
//
//   Hank Childs, Thu Mar 30 12:11:43 PST 2006
//   Add some checking for indices.
//
// *******************************************************************

const avtDefaultPlotMetaData *
avtDatabaseMetaData::GetDefaultPlot(int n) const
{
    if (n < 0 || n >= GetNumDefaultPlots())
        EXCEPTION2(BadIndexException, n, GetNumDefaultPlots());

    return (const avtDefaultPlotMetaData *)defaultPlots[n];
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::SetBlocksForMesh
//
//  Purpose:
//      Resets the number of blocks a mesh can have without violating
//      encapsulation.
//
//  Arguments:
//      index    The index of the mesh in the std::vector "meshes".
//      nBlocks  The number of blocks the mesh actually has.
//
//  Programmer:  Hank Childs
//  Creation:    October 11, 2001
//
// ****************************************************************************

void
avtDatabaseMetaData::SetBlocksForMesh(int index, int nBlocks)
{
    if (index < 0 || index >= GetNumMeshes())
    {
        EXCEPTION2(BadIndexException, index, GetNumMeshes());
    }

    GetMeshes(index).numBlocks = nBlocks;
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::SetContainsGhostZones
//
//  Purpose:
//      Sets whether a particular mesh has ghost zones.
//
//  Arguments:
//      name     The name of a mesh.
//      val      True if it has ghost zones, false otherwise.
//
//  Programmer:  Hank Childs
//  Creation:    September 30, 2002
//
//  Modifications:
//
//    Hank Childs, Fri Aug  1 21:58:01 PDT 2003
//    No longer throw an exception.  This is a valid case for curves.
//
// ****************************************************************************

void
avtDatabaseMetaData::SetContainsGhostZones(std::string name, avtGhostType val)
{
    for (int i = 0 ; i < GetNumMeshes() ; i++)
    {
        if (GetMeshes(i).name == name)
        {
            GetMeshes(i).containsGhostZones = val;
            return;
        }
    }
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::GetContainsGhostZones
//
//  Purpose:
//      Gets whether a particular mesh has ghost zones.
//
//  Arguments:
//      name     The name of a mesh.
//      val      True if it has ghost zones, false otherwise.
//
//  Programmer:  Mark C. Miller
//  Creation:    August 10, 2004
//
// ****************************************************************************

avtGhostType
avtDatabaseMetaData::GetContainsGhostZones(std::string name) const
{
    for (int i = 0 ; i < GetNumMeshes() ; i++)
    {
        if (GetMeshes(i).name == name)
        {
            return GetMeshes(i).containsGhostZones;
        }
    }
    return AVT_MAYBE_GHOSTS;
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::SetContainsOriginalCells
//
//  Purpose:
//      Sets whether a particular mesh has original cells array.
//
//  Arguments:
//      name     The name of a mesh.
//      val      True if it has original cells, false otherwise.
//
//  Programmer:  Kathleen Bonnell
//  Creation:    March 25, 2003
//
//  Modifications:
//
//    Hank Childs, Fri Aug  1 21:58:01 PDT 2003
//    No longer throw an exception.  This is a valid case for curves.
//
// ****************************************************************************

void
avtDatabaseMetaData::SetContainsOriginalCells(std::string name, bool val)
{
    for (int i = 0 ; i < GetNumMeshes() ; i++)
    {
        if (GetMeshes(i).name == name)
        {
            GetMeshes(i).containsOriginalCells = val;
            return;
        }
    }
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::SetContainsOriginalNodes
//
//  Purpose:
//      Sets whether a particular mesh has original nodes array.
//
//  Arguments:
//      name     The name of a mesh.
//      val      True if it has origina nodes,  false otherwise.
//
//  Programmer:  Kathleen Bonnell
//  Creation:    May 28, 2004
//
//  Modifications:
//
// ****************************************************************************

void
avtDatabaseMetaData::SetContainsOriginalNodes(std::string name, bool val)
{
    for (int i = 0 ; i < GetNumMeshes() ; i++)
    {
        if (GetMeshes(i).name == name)
        {
            GetMeshes(i).containsOriginalNodes = val;
            return;
        }
    }
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::SetContainsGlobalNodeIds
//
//  Purpose:
//      Sets whether a particular mesh has global node ids array.
//
//  Programmer:  Mark C. Miller
//  Creation:    August 9, 2004
//
// ****************************************************************************

void
avtDatabaseMetaData::SetContainsGlobalNodeIds(std::string name, bool val)
{
    for (int i = 0 ; i < GetNumMeshes() ; i++)
    {
        if (GetMeshes(i).name == name)
        {
            GetMeshes(i).containsGlobalNodeIds = val;
            return;
        }
    }
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::SetContainsGlobalZoneIds
//
//  Purpose:
//      Sets whether a particular mesh has global zone ids array.
//
//  Programmer:  Mark C. Miller
//  Creation:    August 9, 2004
//
// ****************************************************************************

void
avtDatabaseMetaData::SetContainsGlobalZoneIds(std::string name, bool val)
{
    for (int i = 0 ; i < GetNumMeshes() ; i++)
    {
        if (GetMeshes(i).name == name)
        {
            GetMeshes(i).containsGlobalZoneIds = val;
            return;
        }
    }
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::SetZonesWereSplit
//
//  Purpose:
//      Sets whether a particular mesh's zones were split
//
//  Programmer:  Kathleen Biagas
//  Creation:    July 23, 2014
//
// ****************************************************************************

void
avtDatabaseMetaData::SetZonesWereSplit(std::string name, bool val)
{
    for (int i = 0 ; i < GetNumMeshes() ; i++)
    {
        if (GetMeshes(i).name == name)
        {
            GetMeshes(i).zonesWereSplit = val;
            return;
        }
    }
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::AddGroupInformation
//
//  Purpose:
//      Sets the group information for all applicable meshes in this object.
//      They are applicable if they have the correct number of blocks.
//
//  Arguments:
//      nGroups   The total number of groups.
//      nBlocks   The number of blocks in the mesh.
//      groupIds  The group index for each block.
//
//  Programmer:  Hank Childs
//  Creation:    October 11, 2001
//
// ****************************************************************************

void
avtDatabaseMetaData::AddGroupInformation(int nGroups, int nBlocks,
                                         std::vector<int> &groupIds)
{
    for (int i = 0 ; i < GetNumMeshes() ; i++)
    {
        if (GetMeshes(i).numBlocks == nBlocks)
        {
            GetMeshes(i).numGroups = nGroups;
            GetMeshes(i).groupIds  = groupIds;
        }
    }
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::SetExtents
//
//  Purpose:
//      Sets the extents of a variable.
//
//  Arguments:
//      name      The name of the variable to set extents for.
//      extents   The extents for the variable.
//
//  Programmer: Hank Childs
//  Creation:   August 30, 2000
//
//  Modifications:
//    Kathleen Bonnell, Thu Aug 28 13:42:03 PDT 2003
//    Test for 'name' matching 'blockTitle' or 'groupTitle' in MeshMetaData.
//
//    Brad Whitlock, Wed Mar 7 17:36:17 PST 2007
//    Rewrote for new object representation.
//
// ****************************************************************************

void
avtDatabaseMetaData::SetExtents(std::string name, const double *extents)
{
    bool foundVar = false;
    int  i;

    for (i = 0; i < GetNumMeshes(); ++i)
    {
        avtMeshMetaData &m = GetMeshes(i);
        if ((m.name == name) ||
            (m.blockTitle == name) ||
            (m.groupTitle == name))
        {
            m.SetExtents(extents);
            foundVar = true;
        }
    }

    for (i = 0; i < GetNumScalars(); ++i)
    {
        if (GetScalars(i).name == name)
        {
            GetScalars(i).SetExtents(extents);
            foundVar = true;
        }
    }

    for (i = 0; i < GetNumVectors(); ++i)
    {
        if (GetVectors(i).name == name)
        {
            GetVectors(i).SetExtents(extents);
            foundVar = true;
        }
    }

    if (! foundVar)
    {
        EXCEPTION1(InvalidVariableException, name);
    }
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::UnsetExtents
//
//  Purpose:
//      Allows all of the extents for all of the meshes, scalar vars, and
//      std::vector vars to be unset at one time.
//
//  Programmer:  Hank Childs
//  Creation:    March 6, 2002
//
// ****************************************************************************

void
avtDatabaseMetaData::UnsetExtents(void)
{
    int  i;

    for (i = 0 ; i < GetNumMeshes() ; i++)
    {
        GetMeshes(i).UnsetExtents();
    }
    for (i = 0 ; i < GetNumScalars() ; i++)
    {
        GetScalars(i).UnsetExtents();
    }
    for (i = 0 ; i < GetNumVectors() ; i++)
    {
        GetVectors(i).UnsetExtents();
    }
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::AddExpression
//
//  Purpose:
//      Adds a new expression to the database.
//
//  Programmer: Hank Childs
//  Creation:   September 4, 2002
//
//  Mark C. Miller, Thu Jun 16 18:23:24 PDT 2016
//  Remove leading slash, if any, from expression name.
// ****************************************************************************

void
avtDatabaseMetaData::AddExpression(Expression *_expr)
{
    Expression expr = *_expr;
    std::string exprName = expr.GetName();
    if (exprName[0] == '/')
        expr.SetName(&exprName[1]);
    expr.SetFromDB(true);
    expr.SetDbName(databaseName);
    exprList.AddExpressions(expr);
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::GetExpression
//
//  Purpose:
//      Get a particular expression.
//
//  Programmer: Hank Childs
//  Creation:   September 4, 2002
//
// ****************************************************************************

const Expression *
avtDatabaseMetaData::GetExpression(int expr) const
{
    return &(exprList[expr]);
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::GetNumberOfExpressions
//
//  Purpose:
//      Get the number of expressions defined for this database.
//
//  Programmer: Hank Childs
//  Creation:   September 4, 2002
//
// ****************************************************************************

int
avtDatabaseMetaData::GetNumberOfExpressions(void) const
{
    return exprList.GetNumExpressions();
}

// ****************************************************************************
//  Function: ConvertCSGDomainId
//
//  Purpose: Handle spoofing of CSG domain ids
//
//  A vtkCSGGrid object served up by a plugin is a bunch of CSG regions, not
//  just one region. It is most intuitive to have each region treated as a
//  VisIt "domain." However, that means that VisIt's notion of domains DOES
//  NOT map 1:1 to vtkCSGGrid objects because a single vtkCSGGrid object
//  represents multiple domains. The problem is further complicated by the
//  "multi-block" case where we have multiple vtkCSGGrid objects knitted together
//  to form a multi-block CSG mesh.
//
//  To deal with this, we adopt the convention to treat each region of a single
//  vtkCSGGrid object as a VisIt domain and multiple vtkCSGGrid objects as
//  "groups" of domains.
//
//  This function maps VisIt's domain ids into a block number (e.g. which of
//  the multiple vtkCSGGrid objects) and a region number within the block
//  (e.g. which region within the vtkCSGGrid object)
//
//  Programmer: Mark C. Miller
//  Creation:   June 28, 2006
//
//  Modifications:
//    Mark C. Miller, Tue Dec  5 18:14:58 PST 2006
//    Fixed possible reference through 0
//
// ****************************************************************************
bool
avtDatabaseMetaData::ConvertCSGDomainToBlockAndRegion(const char *const var,
    int *domain, int *region) const
{
    int domainAsVisItSeesIt = *domain;
    std::string meshname = MeshForVar(var);
    const avtMeshMetaData *mmd = GetMesh(meshname);
    if (mmd && mmd->meshType == AVT_CSG_MESH)
    {
        const intVector& groupIds = mmd->groupIds;
        if (groupIds.size() > (size_t)domainAsVisItSeesIt)
        {
            int i, j = groupIds[domainAsVisItSeesIt];
            for (i = domainAsVisItSeesIt; i >= 0 && groupIds[i] == j; i--)
                ; // no-op
            *domain = j;
            if (region) *region = domainAsVisItSeesIt - i + 1;
        }
        else
        {
            *domain = 0;
            if (region) *region = domainAsVisItSeesIt;
        }
        return true;
    }
    return false;
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::GetNDomains
//
//  Purpose:
//      Gets the number of domains for this variable.
//
//  Arguments:
//      var     A variable name.
//
//  Returns:    The number of domains for var.
//
//  Programmer: Hank Childs
//  Creation:   August 31, 2000
//
//  Modifications:
//
//    Hank Childs, Fri Aug  1 21:50:51 PDT 2003
//    Added support for curves.
//
//    Hank Childs, Fri Sep 12 09:11:26 PDT 2003
//    Re-wrote so this could be designated const.
//
//    Hank Childs, Mon Dec  1 14:06:19 PST 2003
//    Made a more informative error message.
//
// ****************************************************************************

int
avtDatabaseMetaData::GetNDomains(const std::string &var) const
{
    int  i;

    std::string  meshname = MeshForVar(var);

    int nmeshes = GetNumMeshes();
    for (i = 0 ; i < nmeshes ; i++)
        if (VariableNamesEqual(GetMeshes(i).name, meshname))
            return GetMeshes(i).numBlocks;

    int ncurves = GetNumCurves();
    for (i = 0 ; i < ncurves ; i++)
    {
        if (VariableNamesEqual(GetCurves(i).name, meshname))
        {
            return 1;
        }
    }

    debug1 << "Unable to find mesh \"" << meshname.c_str() << "\" associated with "
           << "variable \"" << var.c_str() << "\"." << endl;
    EXCEPTION1(InvalidVariableException, var);
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::DetermineVarType
//
//  Purpose:
//      Determines the type of the variable argument.
//
//  Arguments:
//      var_in    A variable name.
//      do_expr   Whether or not to do expressions.
//
//  Returns:    The type of var.
//
//  Programmer: Hank Childs
//  Creation:   August 31, 2000
//
//  Modifications:
//    Kathleen Bonnell, Thu Sep  5 13:53:15 PDT 2002
//    If var is compound, parse it.
//
//    Hank Childs, Fri Aug  1 11:08:21 PDT 2003
//    Add support for curves.
//
//    Sean Ahern, Wed Feb  5 16:30:36 PST 2003
//    Added support for expressions.
//
//    Kathleen Bonnell, Thu Aug 28 13:42:03 PDT 2003
//    Test for 'var' matching 'blockTitle' or 'groupTitle' in MeshMetaData.
//
//    Hank Childs, Fri Sep 12 09:11:26 PDT 2003
//    Made modification so that routine could be 'const'.
//
//    Hank Childs, Sat Sep 20 08:32:38 PDT 2003
//    Add support for tensors.
//
//    Brad Whitlock, Fri Apr 1 15:27:41 PST 2005
//    Added support for labels.
//
//    Hank Childs, Tue Jul 19 13:24:19 PDT 2005
//    Added support for arrays.
//
//    Hank Childs, Sun Feb 19 10:57:47 PST 2006
//    Only get information from expressions based on argument value.
//
//    Hank Childs, Wed May 24 11:00:03 PDT 2006
//    For expression variables, return the type of the expression, not the
//    type of a real variable in that expression.
//
//    Kathleen Bonnell, Fri Sep 28 13:34:13 PDT 2007
//    Use 'VariableNamesEqual' instead of '=='.
//
//    Brad Whitlock, Tue Jan 20 16:01:51 PST 2009
//    Change conversion function.
//
// ****************************************************************************

avtVarType
avtDatabaseMetaData::DetermineVarType(std::string var_in, bool do_expr) const
{
    int  i;

    // If the variable is an expression, we need to find a "real" variable
    // name to work with.
    if (do_expr)
    {
        ParsingExprList *pel = ParsingExprList::Instance();
        Expression const *e = pel->GetExpression(var_in);
        if (e != NULL)
            return ExprType_To_avtVarType(e->GetType());
    }

    std::string var;
    if (!VarIsCompound(var_in))
    {
        var = var_in;
    }
    else
    {
        ParseCompoundForVar(var_in, var);
    }

    int nmeshes = GetNumMeshes();
    for (i = 0 ; i < nmeshes ; i++)
    {
        if ((VariableNamesEqual(GetMeshes(i).name, var)) ||
            (VariableNamesEqual(GetMeshes(i).blockTitle, var)) ||
            (VariableNamesEqual(GetMeshes(i).groupTitle, var)))
        {
            return AVT_MESH;
        }
    }

    int nvectors = GetNumVectors();
    for (i = 0 ; i < nvectors ; i++)
    {
        if (VariableNamesEqual(GetVectors(i).name, var))
        {
            return AVT_VECTOR_VAR;
        }
    }

    int ntensors = GetNumTensors();
    for (i = 0 ; i < ntensors ; i++)
    {
        if (VariableNamesEqual(GetTensors(i).name, var))
        {
            return AVT_TENSOR_VAR;
        }
    }

    int nsymmtensors = GetNumSymmTensors();
    for (i = 0 ; i < nsymmtensors ; i++)
    {
        if (VariableNamesEqual(GetSymmTensors(i).name, var))
        {
            return AVT_SYMMETRIC_TENSOR_VAR;
        }
    }

    int narrays = GetNumArrays();
    for (i = 0 ; i < narrays ; i++)
    {
        if (VariableNamesEqual(GetArrays(i).name, var))
        {
            return AVT_ARRAY_VAR;
        }
    }

    int nscalars = GetNumScalars();
    for (i = 0 ; i < nscalars ; i++)
    {
        if (VariableNamesEqual(GetScalars(i).name, var))
        {
            return AVT_SCALAR_VAR;
        }
    }

    int nmats = GetNumMaterials();
    for (i = 0 ; i < nmats ; i++)
    {
        if (VariableNamesEqual(GetMaterials(i).name, var))
        {
            return AVT_MATERIAL;
        }
    }

    int nspecies = GetNumSpecies();
    for (i = 0 ; i < nspecies ; i++)
    {
        if (VariableNamesEqual(GetSpecies(i).name, var))
        {
            return AVT_MATSPECIES;
        }
    }

    int ncurves = GetNumCurves();
    for (i = 0 ; i < ncurves ; i++)
    {
        if (VariableNamesEqual(GetCurves(i).name, var))
        {
            return AVT_CURVE;
        }
    }

    int nlabels = GetNumLabels();
    for (i = 0 ; i < nlabels ; i++)
    {
        if (VariableNamesEqual(GetLabels(i).name, var))
        {
            return AVT_LABEL_VAR;
        }
    }

    return AVT_UNKNOWN_TYPE;
}

// ****************************************************************************
//  Function: avtDatabaseMetaData::DetermineSubsetType
//
//  Purpose:
//    Determines the subset type of the passed  compound variable of the form
//    'CategoryName(MeshName)'.
//
//  Arguments:
//    inVar   The (possibly) compound variable.
//
//  Returns:
//    The subset type (AVT_UNKNOWN_SUBSET) if inVar is not compound.
//
//  Programmer: Kathleen Bonnell
//  Creation:   September 5, 2002
//
//  Modifications:
//    Kathleen Bonnell, Fri Aug 22 18:02:15 PDT 2003
//    Subset vars are no longer always 'compound', parse accordingly.
//
//    Jeremy Meredith, Wed Aug 23 18:23:16 EDT 2006
//    Find enumerated scalar type subsets.
//
//    Mark C. Miller, Mon Apr 14 15:17:17 PDT 2008
//    Changed interface to enum scalar
//
// ****************************************************************************

avtSubsetType
avtDatabaseMetaData::DetermineSubsetType(const std::string &inVar) const
{
    std::string category, mesh;

    if (VarIsCompound(inVar))
    {
        ParseCompoundForMesh(inVar, mesh);
        ParseCompoundForCategory(inVar, category);
    }
    else
    {
        category = inVar;
        mesh = MeshForVar(inVar);
    }

    //
    // determine which part of the var we want to return
    // HACKISH ... only checking domains, and probably incorrectly at that!
    //
    const avtMeshMetaData *mmd = GetMesh(mesh);
    std::string blockTitle;
    std::string groupTitle;
    if (mmd == NULL)
    {
        blockTitle = "domains";   // Not a lot we can do.
        groupTitle = "blocks";
    }
    else
    {
        blockTitle = mmd->blockTitle;
        groupTitle = mmd->groupTitle;
    }

    //
    // Check Blocks/Domains and Groups first
    //
    if (category == blockTitle)
    {
        return AVT_DOMAIN_SUBSET;
    }
    else if (category == groupTitle)
    {
        return AVT_GROUP_SUBSET;
    }

    //
    // Check material next
    //
    const avtMaterialMetaData *matmd = GetMaterialOnMesh(mesh);

    if (matmd != NULL && matmd->name == category)
        return AVT_MATERIAL_SUBSET;
    //
    // Check enumerated scalars next
    //
    const avtScalarMetaData *smd = GetScalar(category);
    if (smd != NULL && smd->GetEnumerationType() != avtScalarMetaData::None)
        return AVT_ENUMSCALAR_SUBSET;

    //
    // No match on any known subset types
    //
    return AVT_UNKNOWN_SUBSET;
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::MeshForVar
//
//  Purpose:
//      Determines the mesh that the variable argument is defined on.
//
//  Arguments:
//      var     A variable name.
//
//  Returns:    The mesh that var is defined on.
//
//  Programmer: Hank Childs
//  Creation:   August 31, 2000
//
//  Modifications:
//    Kathleen Bonnell, Thu Sep  5 13:53:15 PDT 2002
//    If var is compound, parse it.
//
//    Hank Childs, Fri Aug  1 21:35:00 PDT 2003
//    Have curve plots return themselves.
//
//    Sean Ahern, Fri Dec 13 11:04:50 PST 2002
//    Added expression support.
//
//    Kathleen Bonnell, Thu Aug 28 13:42:03 PDT 2003
//    Test for 'var' matching 'blockTitle' or 'groupTitle' in MeshMetaData.
//
//    Hank Childs, Fri Sep 12 09:17:33 PDT 2003
//    Re-coded some sections so this routine could be 'const'.
//
//    Hank Childs, Sat Sep 20 08:49:16 PDT 2003
//    Add support for tensors.
//
//    Jeremy Meredith, Tue Dec 14 14:02:35 PST 2004
//    The code to get the real variable name was a duplicate of two
//    other spots in VisIt, but this one was out of date.  I
//    refactored the best one into ParsingExprList::GetRealVariable
//    and made this one point to it.
//
//    Brad Whitlock, Fri Apr 1 15:28:35 PST 2005
//    Added support for labels.
//
//    Hank Childs, Tue Jul 19 13:24:19 PDT 2005
//    Added support for arrays.
//
//    Mark C. Miller, Mon Aug 21 18:47:45 PDT 2006
//    Added test for numBlocks>1 to matching on block/groupTitle
//
//    Brad Whitlock, Wed Mar 7 15:05:09 PST 2007
//    Changed for automatic generation.
//
//    Cyrus Harrison, Wed Aug 25 08:35:22 PDT 2010
//    Support selection of domains, even if we only have
//    a single domain.
//
// ****************************************************************************

std::string
avtDatabaseMetaData::MeshForVar(const std::string &invar) const
{
    int   i;
    std::string var(invar);

    // Check if we even have a variable.
    if (var == "")
    {
        debug1 << "avtDatabaseMetaData::MeshForVar: Null variable passed."
               << endl;
        EXCEPTION1(InvalidVariableException, var);
    }

    // If the variable is an expression, we need to find a "real" variable
    // name to work with.
    var = ParsingExprList::GetRealVariable(var);

    // If the variable is compound, parse out the variable name.
    if (VarIsCompound(var))
    {
        std::string meshName;
        ParseCompoundForMesh(var, meshName);
        return meshName;
    }

    // Look through the meshes.
    int nmeshes = GetNumMeshes();
    for (i = 0 ; i < nmeshes ; i++)
    {
        if (VariableNamesEqual(GetMeshes(i).name, var))
        {
            //
            // The mesh is defined on itself??  A little weird, but this is
            // convenient for some routines.
            //
            return var;
        }
        else if ( VariableNamesEqual(GetMeshes(i).blockTitle, var) ||
                  VariableNamesEqual(GetMeshes(i).groupTitle, var))
        {
            return GetMeshes(i).name;
        }
    }

    // Look through the vectors.
    int nvectors = GetNumVectors();
    for (i = 0 ; i < nvectors ; i++)
    {
        if (VariableNamesEqual(GetVectors(i).name, var))
        {
            return GetVectors(i).meshName;
        }
    }

    // Look through the tensors.
    int ntensors = GetNumTensors();
    for (i = 0 ; i < ntensors ; i++)
    {
        if (VariableNamesEqual(GetTensors(i).name, var))
        {
            return GetTensors(i).meshName;
        }
    }

    // Look through the symmteric tensors.
    int nsymmtensors = GetNumSymmTensors();
    for (i = 0 ; i < nsymmtensors ; i++)
    {
        if (VariableNamesEqual(GetSymmTensors(i).name, var))
        {
            return GetSymmTensors(i).meshName;
        }
    }

    // Look through the arrays.
    int narrays = GetNumArrays();
    for (i = 0 ; i < narrays ; i++)
    {
        if (VariableNamesEqual(GetArrays(i).name, var))
        {
            return GetArrays(i).meshName;
        }
    }

    // Look through the scalars.
    int nscalars = GetNumScalars();
    for (i = 0 ; i < nscalars ; i++)
    {
        if (VariableNamesEqual(GetScalars(i).name, var))
        {
            return GetScalars(i).meshName;
        }
    }

    // Look through the materials.
    int nmats = GetNumMaterials();
    for (i = 0 ; i < nmats ; i++)
    {
        if (VariableNamesEqual(GetMaterials(i).name, var))
        {
            return GetMaterials(i).meshName;
        }
    }

    // Look through the species.
    int nspecies = GetNumSpecies();
    for (i = 0 ; i < nspecies ; i++)
    {
        if (VariableNamesEqual(GetSpecies(i).name, var))
        {
            return GetSpecies(i).meshName;
        }
    }

    // Look through the curves.
    int ncurves = GetNumCurves();
    for (i = 0 ; i < ncurves ; i++)
    {
        if (VariableNamesEqual(GetCurves(i).name, var))
        {
            return var;
        }
    }

    // Look through the labels.
    int nlabels = GetNumLabels();
    for (i = 0 ; i < nlabels ; i++)
    {
        if (VariableNamesEqual(GetLabels(i).name, var))
        {
            return GetLabels(i).meshName;
        }
    }

    EXCEPTION1(InvalidVariableException, var);
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::MaterialOnMesh
//
//  Purpose:
//      Finds a material for a mesh.
//
//  Arguments:
//      mesh    A mesh name.
//
//  Returns:    The name of a material defined on that mesh.
//
//  Programmer: Hank Childs
//  Creation:   December 13, 2000
//
//  Modifications:
//
//    Hank Childs, Thu Mar  6 14:52:23 PST 2003
//    Issue a warning to the debug files if there are multiple materials on a
//    mesh.
//
//    Hank Childs, Fri Sep 12 09:17:33 PDT 2003
//    Re-coded some sections so this routine could be 'const'.
//
//    Brad Whitlock, Wed Mar 7 15:06:22 PST 2007
//    Changed for automatic generation.
//
//    Cyrus Harrison, Fri Feb 22 09:01:53 PST 2008
//    Provided better exception message if a material was not found.
//
// ****************************************************************************

std::string
avtDatabaseMetaData::MaterialOnMesh(const std::string &mesh) const
{
    std::string rv = "";
    bool foundValue = false;

    int nmats = GetNumMaterials();
    for (int i = 0 ; i < nmats ; i++)
    {
        if (VariableNamesEqual(GetMaterials(i).meshName, mesh))
        {
            if (foundValue)
            {
                debug1 << "WARNING: screwy file.  There are multiple materials"
                       << " (" << rv.c_str() << " and "
                       << GetMaterials(i).name.c_str() << ") defined"
                       << " on the same mesh." << endl;
                debug1 << "There are assumption in the VisIt code that this "
                       << "will never happen." << endl;
            }

            rv = GetMaterials(i).name;
            foundValue = true;
        }
    }

    if (foundValue)
    {
        return rv;
    }

    std::string err_msg = "Cannot find Material Object for mesh =\"";
    err_msg +=  mesh + "\".";
    EXCEPTION1(VisItException,err_msg.c_str());
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::SpeciesOnMesh
//
//  Purpose:
//      Finds a species for a mesh.
//
//  Arguments:
//      mesh    A mesh name.
//
//  Returns:    The name of a species defined on that mesh.
//
//  Programmer: Jeremy Meredith
//  Creation:   December 17, 2001
//
//  Modifications:
//
//    Hank Childs, Fri Sep 12 09:17:33 PDT 2003
//    Re-coded some sections so this routine could be 'const'.
//
// ****************************************************************************

std::string
avtDatabaseMetaData::SpeciesOnMesh(const std::string &mesh) const
{
    int nspecies = GetNumSpecies();
    for (int i = 0 ; i < nspecies ; i++)
    {
        if (VariableNamesEqual(GetSpecies(i).meshName, mesh))
        {
            return GetSpecies(i).name;
        }
    }

    EXCEPTION1(InvalidVariableException, mesh);
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::GetMaterialOnMesh
//
//  Purpose:
//      Gets a material for a mesh and returns it.
//
//  Arguments:
//      mesh    A mesh name.
//
//  Returns:    The material defined on that mesh.
//
//  Programmer: Hank Childs
//  Creation:   March 12, 2001
//
//  Modifications:
//
//    Hank Childs, Thu Mar  6 14:52:23 PST 2003
//    Issue a warning to the debug files if there are multiple materials on a
//    mesh.
//
//    Hank Childs, Fri Sep 12 09:17:33 PDT 2003
//    Re-coded some sections so this routine could be 'const'.
//
// ****************************************************************************

const avtMaterialMetaData *
avtDatabaseMetaData::GetMaterialOnMesh(const std::string &mesh) const
{
    const avtMaterialMetaData *rv = NULL;

    int nmaterials = GetNumMaterials();
    for (int i = 0 ; i < nmaterials ; i++)
    {
        if (VariableNamesEqual(GetMaterials(i).meshName, mesh))
        {
            if (rv != NULL)
            {
                debug1 << "WARNING: screwy file.  There are multiple materials"
                       << " (" << rv << " and " << GetMaterials(i).name.c_str()
                       << ") defined on the same mesh." << endl;
                debug1 << "There are assumptions in the VisIt code that this "
                       << "will never happen." << endl;
            }
            rv = GetMaterial(i);
        }
    }

    return rv;
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::GetSpeciesOnMesh
//
//  Purpose:
//      Gets a species for a mesh and returns it.
//
//  Arguments:
//      mesh    A mesh name.
//
//  Returns:    The species defined on that mesh.
//
//  Programmer: Jeremy Meredith
//  Creation:   December 14, 2001
//
//  Modifications:
//
//    Hank Childs, Fri Sep 12 09:17:33 PDT 2003
//    Re-coded some sections so this routine could be 'const'.
//
// ****************************************************************************

const avtSpeciesMetaData *
avtDatabaseMetaData::GetSpeciesOnMesh(const std::string &mesh) const
{
    for (int i = 0 ; i < GetNumSpecies() ; i++)
    {
        if (VariableNamesEqual(GetSpecies(i).meshName, mesh))
        {
            return (const avtSpeciesMetaData *)species[i];
        }
    }

    return NULL;
}

// ****************************************************************************
//  Function: GetAllVariableNames
//
//  Purpose:
//    Retrieves names of all variables defined on a particular mesh.
//
//  Arguments:
//    activeVar The active variable for the pipeline, used to determine
//              the mesh the vars should be defined on.
//
//  Returns:
//    A list of variable names defined on the same mesh as the active var.
//
//  Programmer: Kathleen Bonnell
//  Creation:   August 24, 2004
//
//  Modifications:
//    Brad Whitlock, Fri Apr 1 22:53:25 PST 2005
//    Added labels.
//
//    Hank Childs, Tue Jul 19 13:24:19 PDT 2005
//    Added support for arrays.
//
// ****************************************************************************

const stringVector
avtDatabaseMetaData::GetAllVariableNames(const std::string &activeVar) const
{
    int i;
    stringVector vars;
    std::string meshName = MeshForVar(activeVar);
    for (i = 0; i < GetNumScalars(); i++)
    {
        if (VariableNamesEqual(GetScalars(i).meshName, meshName))
            vars.push_back(GetScalars(i).name);
    }
    for (i = 0; i < GetNumVectors(); i++)
    {
        if (VariableNamesEqual(GetVectors(i).meshName, meshName))
            vars.push_back(GetVectors(i).name);
    }
    for (i = 0; i < GetNumTensors(); i++)
    {
        if (VariableNamesEqual(GetTensors(i).meshName, meshName))
            vars.push_back(GetTensors(i).name);
    }
    for (i = 0; i < GetNumSymmTensors(); i++)
    {
        if (VariableNamesEqual(GetSymmTensors(i).meshName, meshName))
            vars.push_back(GetSymmTensors(i).name);
    }
    for (i = 0; i < GetNumArrays(); i++)
    {
        if (VariableNamesEqual(GetArrays(i).meshName, meshName))
            vars.push_back(GetArrays(i).name);
    }
    for (i = 0; i < GetNumMaterials(); i++)
    {
        if (VariableNamesEqual(GetMaterials(i).meshName, meshName))
            vars.push_back(GetMaterials(i).name);
    }
    for (i = 0; i < GetNumSpecies(); i++)
    {
        if (VariableNamesEqual(GetSpecies(i).meshName, meshName))
            vars.push_back(GetSpecies(i).name);
    }
    for (i = 0; i < GetNumLabels(); i++)
    {
        if (VariableNamesEqual(GetLabels(i).meshName, meshName))
            vars.push_back(GetLabels(i).name);
    }
    return vars;
}

// ****************************************************************************
//  Function: GetAllMeshNames
//
//  Purpose:
//    Retrieves names of all mesh defined on this database.
//
//  Returns:
//    A list of mesh names.
//
//  Programmer: Kathleen Bonnell
//  Creation:   January 21, 2005
//
//  Modifications:
//
// ****************************************************************************

stringVector
avtDatabaseMetaData::GetAllMeshNames() const
{
    int i;
    stringVector meshNames;
    for (i = 0; i < GetNumMeshes(); i++)
    {
        meshNames.push_back(GetMeshes(i).name);
    }
    return meshNames;
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::Print
//
//  Purpose:
//      Prints out all of the meta-data objects in the database meta-data
//      object.  Meant for debugging only.
//
//  Arguments:
//      out     The stream to print out to.
//      indent  The indentation level for each line.
//
//  Programmer: Hank Childs
//  Creation:   August 28, 2000
//
//  Modifications:
//
//    Jeremy Meredith, Tue Sep 12 14:58:42 PDT 2000
//    Added code to print the number of time states.
//
//    Hank Childs, Fri Sep 15 19:07:21 PDT 2000
//    Print out Temporal extents and cycles.
//
//    Brad Whitlock, Tue Aug 20 15:23:59 PST 2002
//    I made it so categories that contain no entries are not printed.
//
//    Hank Childs, Wed Sep  4 11:32:48 PDT 2002
//    Print out information related to expressions.
//
//    Sean Ahern, Fri Dec 13 16:50:58 PST 2002
//    Changed to use the ExprssionList state objects.
//
//    Sean Ahern, Mon Mar 17 23:48:43 America/Los_Angeles 2003
//    Changed the names of expression types.
//
//    Brad Whitlock, Wed Apr 2 12:01:10 PDT 2003
//    I made it print out the timestep names if it is a virtual database.
//
//    Hank Childs, Fri Aug  1 11:08:21 PDT 2003
//    Add support for curves.
//
//    Hank Childs, Sat Sep 20 08:49:16 PDT 2003
//    Add support for tensors.
//
//    Hank Childs, Fri Mar  5 11:21:06 PST 2004
//    Print file format.
//
//    Mark C. Miller, Tue Mar 30 14:36:17 PST 2004
//    Added useCatchAllMesh
//
//    Jeremy Meredith, Wed Jul 21 14:23:12 PDT 2004
//    Removed the exclamation point from unknown.
//
//    Brad Whitlock, Fri Jul 23 12:37:57 PDT 2004
//    Added databaseComment.
//
//    Jeremy Meredith, Thu Aug 12 13:23:25 PDT 2004
//    Added simulation fields.
//
//    Mark C. Miller, Tue Sep 28 19:57:42 PDT 2004
//    Added formatCanDoDomainDecomposition
//
//    Brad Whitlock, Fri Apr 1 15:28:58 PST 2005
//    Added labels.
//
//    Mark C. Miller, Tue May 17 18:48:38 PDT 2005
//    Added code to deal with printing of times and a friendlier format
//    for printing of cycles and times
//
//    Hank Childs, Tue Jul 19 13:25:53 PDT 2005
//    Added arrays.
//
//    Kathleen Bonnell, Thu Aug  3 08:42:33 PDT 2006
//    Added CurveMeshVar.
//
// ****************************************************************************

inline void
Indent(ostream &out, int indent)
{
    for (int i = 0 ; i < indent ; i++)
    {
        out << "\t";
    }
}
void
avtDatabaseMetaData::Print(ostream &out, int indent) const
{
    Indent(out, indent);
    out << "Database: " << databaseName.c_str() << endl;

    Indent(out, indent);
    out << "Simulation: " << (isSimulation ? "Yes" : "No" ) << endl;

    Indent(out, indent);
    out << "Database comment: " << databaseComment.c_str() << endl;

    Indent(out, indent);
    out << "File format: " << fileFormat.c_str() << endl;

    Indent(out, indent);
    out << "Num Time States: " << numStates << endl;

    Indent(out, indent);
    out << "MetaData" << (mustRepopulateOnStateChange ? " IS " : " is NOT ") <<
        "repopulated on state changes" << endl;

    Indent(out, indent);
    out << "useCatchAllMesh: " << useCatchAllMesh << endl;

    Indent(out, indent);
    out << "Format " << (formatCanDoDomainDecomposition ? " can " : " cannot ") <<
        "do its own domain decomposition" << endl;

    Indent(out, indent);
    if (hasTemporalExtents)
    {
        out << "Temporal extents are from "
            << minTemporalExtents << " to " << maxTemporalExtents
            << ",  dt = " << (maxTemporalExtents-minTemporalExtents) << "."
            << endl;
    }
    else
    {
        out << "The temporal extents are not set." << endl;
    }

    Indent(out, indent);
    if (times.size() == 0)
    {
        out << "The times are not set." << endl;
    }
    else
    {
        bool shouldPrintTimes = false;
        for (size_t i = 0; i < times.size(); ++i)
        {
            if (times[i] != (double) cycles[i])
            {
                shouldPrintTimes = true;
                break;
            }
        }

        if (AreAllTimesAccurateAndValid())
            out << "All Times are Accurate" << endl;
        else
            out << "All Times are ***NOT*** Accurate" << endl;
        if (shouldPrintTimes)
        {
            out << "Times: " << endl;
            Indent(out, indent+1);
            for (size_t i = 0; i < times.size(); ++i)
            {
                out << times[i];
                if(i < times.size() - 1)
                    out << ", ";
                if((i+1)%5 == 0)
                {
                    out << endl;
                    Indent(out, indent+1);
                }
            }
        }
        else
        {
            out << "Times: Are identical to cycles";
        }
        out << endl;
    }

    Indent(out, indent);
    if (cycles.size() == 0)
    {
        out << "The cycles are not set." << endl;
    }
    else
    {
        if (AreAllCyclesAccurateAndValid())
            out << "All Cycles are Accurate" << endl;
        else
            out << "All Cycles are ***NOT*** Accurate" << endl;
        out << "Cycles: " << endl;
        Indent(out, indent+1);
        for (size_t i = 0; i < cycles.size(); ++i)
        {
            out << cycles[i];
            if(i < cycles.size() - 1)
                out << ", ";
            if((i+1)%10 == 0)
            {
                out << endl;
                Indent(out, indent+1);
            }
        }
        out << endl;
    }

    if(isVirtualDatabase)
    {
        out << endl;
        out << "Database is virtual" << endl;
        out << "Timesteps are located in " << timeStepPath.c_str() << endl;
        out << "Timesteps:" << endl;
        for(size_t i = 0; i < timeStepNames.size(); ++i)
            out << "\t" << timeStepNames[i].c_str() << endl;
        out << endl;
    }

    int i;
    if(GetNumMeshes() > 0)
    {
        Indent(out, indent);
        out << "Meshes: " << endl;
    }
    for (i = 0; i < GetNumMeshes(); ++i)
    {
        GetMeshes(i).Print(out, indent+1);
        out << endl;
    }
    if (GetNumSubsets() > 0)
    {
        Indent(out, indent);
        out << "Subsets: " << endl;
    }
    for (i = 0; i < GetNumSubsets(); i++)
    {
          GetSubsets(i).Print(out, indent+1);
          out << endl;
    }

    if(GetNumScalars() > 0)
    {
        Indent(out, indent);
        out << "Scalars: " << endl;
    }
    for (i = 0; i < GetNumScalars(); ++i)
    {
        GetScalars(i).Print(out, indent+1);
        out << endl;
    }

    if(GetNumVectors() > 0)
    {
        Indent(out, indent);
        out << "Vectors: " << endl;
    }
    for (i = 0; i < GetNumVectors(); ++i)
    {
        GetVectors(i).Print(out, indent+1);
        out << endl;
    }

    if(GetNumTensors() > 0)
    {
        Indent(out, indent);
        out << "Tensors: " << endl;
    }
    for (i = 0; i < GetNumTensors(); ++i)
    {
        GetTensors(i).Print(out, indent+1);
        out << endl;
    }

    if(GetNumSymmTensors() > 0)
    {
        Indent(out, indent);
        out << "Symmetric Tensors: " << endl;
    }
    for (i = 0; i < GetNumSymmTensors(); ++i)
    {
        GetSymmTensors(i).Print(out, indent+1);
        out << endl;
    }

    if(GetNumArrays() > 0)
    {
        Indent(out, indent);
        out << "Arrays: " << endl;
    }
    for (i = 0; i < GetNumArrays(); ++i)
    {
        GetArrays(i).Print(out, indent+1);
        out << endl;
    }

    if(GetNumMaterials() > 0)
    {
        Indent(out, indent);
        out << "Materials: " << endl;
    }
    for (i = 0; i < GetNumMaterials(); ++i)
    {
        GetMaterials(i).Print(out, indent+1);
        out << endl;
    }

    if(GetNumSpecies() > 0)
    {
        Indent(out, indent);
        out << "Material Species: " << endl;
    }
    for (i = 0; i < GetNumSpecies(); ++i)
    {
        GetSpecies(i).Print(out, indent+1);
        out << endl;
    }

    if(curves.begin() != curves.end())
    {
        Indent(out, indent);
        out << "Curves: " << endl;
    }
    for (i = 0; i < GetNumCurves(); ++i)
    {
        GetCurves(i).Print(out, indent+1);
        out << endl;
    }

    if(GetNumLabels() > 0)
    {
        Indent(out, indent);
        out << "Labels: " << endl;
    }
    for (i = 0; i < GetNumLabels(); ++i)
    {
        GetLabels(i).Print(out, indent+1);
        out << endl;
    }

    if(GetNumDefaultPlots() > 0)
    {
        Indent(out, indent);
        out << "Default Plots: " << endl;
    }
    for (i = 0; i < GetNumDefaultPlots(); ++i)
    {
        GetDefaultPlots(i).Print(out, indent+1);
        out << endl;
    }

    if (exprList.GetNumExpressions() > 0)
    {
        Indent(out, indent);
        out << "Expressions:" << endl;
        for (int i = 0 ; i < exprList.GetNumExpressions() ; i++)
        {
            Indent(out, indent+1);
            std::string vartype("unknown var type");
            switch (exprList[i].GetType())
            {
              case Expression::Mesh:
                vartype = "mesh";
                break;
              case Expression::ScalarMeshVar:
                vartype = "scalar";
                break;
              case Expression::VectorMeshVar:
                vartype = "vector";
                break;
              case Expression::TensorMeshVar:
                vartype = "tensor";
                break;
              case Expression::SymmetricTensorMeshVar:
                vartype = "symmetrictensor";
                break;
              case Expression::ArrayMeshVar:
                vartype = "array";
                break;
              case Expression::CurveMeshVar:
                vartype = "curve";
                break;
              case Expression::Material:
                vartype = "material";
                break;
              case Expression::Species:
                vartype = "species";
                break;
              case Expression::Unknown:
                vartype = "unknown";
                break;
            }
            out << exprList[i].GetName().c_str()
                << " (" << vartype.c_str() << "): \t"
                << exprList[i].GetDefinition().c_str() << endl;
        }
    }
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::RegisterWarningCallback
//
//  Purpose:
//      Register a warning callback.
//
//  Programmer: Hank Childs
//  Creation:   February 15, 2005
//
// ****************************************************************************

void
avtDatabaseMetaData::RegisterWarningCallback(void (*WC)(const char *))
{
    WarningCallback = WC;
    haveWarningCallback = true;
}

void    (*avtDatabaseMetaData::WarningCallback)(const char *) = NULL;

bool    avtDatabaseMetaData::haveWarningCallback = false;

// ****************************************************************************
//  Method: avtDatabaseMetaData::IssueWarning
//
//  Purpose:
//      Issues a warning.
//
//  Programmer: Hank Childs
//  Creation:   February 15, 2005
//
// ****************************************************************************

void
avtDatabaseMetaData::IssueWarning(const char *msg) const
{
    if (haveWarningCallback)
    {
        WarningCallback(msg);
    }
    else
    {
        debug1 << "avtDatabaseMetaData wanted to issue the following warning, "
               << "but could not, because no callback was registered:" << endl;
        debug1 << msg << endl;
    }
}

// ****************************************************************************
//  Function: avtDatabaseMetaData::VarIsCompound
//
//  Purpose:
//    Determines if a variable is in compound form: 'CategoryName(MeshName)'.
//
//  Arguments:
//    v       The (possibly) compound variable.
//
//  Returns:
//    true if the variable is in compound form, false otherwise.
//
//  Programmer: Kathleen Bonnell
//  Creation:   September 5, 2002
//
// ****************************************************************************

bool
avtDatabaseMetaData::VarIsCompound(const std::string &v) const
{
    // find the mesh name enclosed in parentheses
    size_t beg = v.find('(');
    size_t end = v.find(')');

    if (beg == std::string::npos || end == std::string::npos)
    {
        return false;
    }
    return true;
}

// ****************************************************************************
//  Function: avtDatabaseMetaData::ParseCompoundForVar
//
//  Purpose:
//    Parses a compound variable of the form 'CategoryName(MeshName)' for
//    the variable portion.
//
// Notes:
//    The desired variable is one that can be 'typed', which may be either
//    CategoryName or MeshName, depending depending upon the subset.
//    e.g. if the CategoryName matches with blockTile or groupTitle of the
//    corresponding MeshMetaData, then the MeshName is returned, so that the
//    variable can be typed as 'AVT_MESH_VAR'.
//
//    This code pulled from gui. (QvisPlotManagerWidget).
//    If inVar is not in the correct compound form, then outVar set to inVar.
//
//  Arguments:
//    inVar   The (possibly) compound variable to parse.
//    outVar  A place to store the parsed variable name.
//
//  Programmer: Kathleen Bonnell
//  Creation:   September 5, 2002
//
// ****************************************************************************

void
avtDatabaseMetaData::ParseCompoundForVar(const std::string &inVar,
    std::string &outVar) const
{
    if (!VarIsCompound(inVar))
    {
        outVar = inVar;
        return;
    }

    avtSubsetType sT = DetermineSubsetType(inVar);

    switch (sT)
    {
        case AVT_DOMAIN_SUBSET : // fall-through
        case AVT_GROUP_SUBSET  :
            ParseCompoundForMesh(inVar, outVar);
            break;
        case AVT_MATERIAL_SUBSET :
            ParseCompoundForCategory(inVar, outVar);
            break;
        default:
            outVar = inVar;
            break;
    }
}

// ****************************************************************************
//  Function: avtDatabaseMetaData::ParseCompoundForMesh
//
//  Purpose:
//    Parses a compound variable of the form 'CategoryName(MeshName)' for
//    the mesh portion.
//
//  Arguments:
//    inVar   The (possibly) compound variable to parse.
//    outVar  A place to store the parsed mesh name.
//
//  Notes:
//    If inVar is not in the correct compound form, then outVar set to inVar.
//
//  Programmer: Kathleen Bonnell
//  Creation:   September 5, 2002
//
// ****************************************************************************

void
avtDatabaseMetaData::ParseCompoundForMesh(const std::string &inVar,
      std::string &outVar) const
{
    // find the mesh name enclosed in parentheses
    size_t beg = inVar.find('(');
    size_t end = inVar.find(')');

    if (beg == std::string::npos || end == std::string::npos)
    {
        // this is not a parseable variable.
        outVar = inVar;
        return;
    }

    //move past the first paren
    beg += 1;
    outVar = inVar.substr(beg, end - beg);
}

// ****************************************************************************
//  Function: avtDatabaseMetaData::ParseCompoundForCategory
//
//  Purpose:
//    Parses a compound variable of the form 'CategoryName(MeshName)' for
//    the category portion.
//
//  Arguments:
//    inVar   The (possibly) compound variable to parse.
//    outVar  A place to store the parsed category name.
//
//  Notes:
//    If inVar is not in the correct compound form, then outVar set to inVar.
//
//  Programmer: Kathleen Bonnell
//  Creation:   September 5, 2002
//
// ****************************************************************************


void
avtDatabaseMetaData::ParseCompoundForCategory(const std::string &inVar,
      std::string &outVar) const
{
    // find the mesh name enclosed in parentheses
    size_t beg = inVar.find('(');
    size_t end = inVar.find(')');

    if (beg == std::string::npos || end == std::string::npos)
    {
        // this is not a compound variable.
        outVar = inVar;
        return;
    }
    outVar = inVar.substr(0, beg);
}

// ****************************************************************************
// Method: avtDatabaseMetaData::VariableNamesEqual
//
// Purpose:
//   Compares variable names and allows "/var" to be the same as "var".
//
// Arguments:
//   v1 : variable 1.
//   v2 : variable 2.
//
// Returns:    True if the variables are equal; false otherwise.
//
// Note:
//
// Programmer: Brad Whitlock
// Creation:   Fri Apr 29 09:37:17 PDT 2005
//
// Modifications:
//
//    Mark C. Miller, Thu Sep 15 11:01:24 PDT 2016
//    Added logic to compare to original v2 or to munged v2new after forbidden
//    char replacement has occured.
// ****************************************************************************

bool
avtDatabaseMetaData::VariableNamesEqual(const std::string &v1, const std::string &v2) const
{
    bool v1BeginsWithSlash = (v1.size() >= 1) ? v1[0] == '/' : false;
    bool v2BeginsWithSlash = (v2.size() >= 1) ? v2[0] == '/' : false;
    std::string v2new;

    IsForbidden(v2, v2new, forbiddenVarNameChars, replacementVarNameStrs);

    if(v1BeginsWithSlash && v2BeginsWithSlash)
        return v1 == v2 || v1 == v2new;
    else if(!v1BeginsWithSlash && !v2BeginsWithSlash)
        return v1 == v2 || v1 == v2new;
    else if(v1BeginsWithSlash)
        return v1.substr(1) == v2 || v1.substr(1) == v2new;
    else
        return v2.substr(1) == v1 || v2new.substr(1) == v1;
}

std::string avtDatabaseMetaData::cycleFromFilenameRegex;

// ****************************************************************************
//  Method: avtDatabaseMetaData::SetCycleFromFilenameRegex
//
//  Purpose: Set regular expression for finding cycles in filenames
//
//  The format of string passed here is an opening '<' followed by the actual
//  regular expression string followed by a closing '>', optionally followed
//  by a ' ' (space) and a backslashed reference to the specific substring
//  containing the cycle digits. For example, to extract the cycle digits
//  from strings looking like 'run_23_0010_yana.silo' where '0010' is the cycle
//  digits, the string to pass here would look like...
//
//                                               V--substring reference
//                      "<.*_([0-9]{4})_.*\\..*> \1"
//          opening char-^                     ^--closing char
//                        ^------RE part------^
//
//  Do a 'man 7 regex' to get more information on regular expression syntax
//
//  Programmer: Mark C. Miller
//  Creation:   June 13, 2007
//
// ****************************************************************************

void
avtDatabaseMetaData::SetCycleFromFilenameRegex(const char *re)
{
    cycleFromFilenameRegex = re;
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::GetCycleFromFilenameRegex
//
//  Purpose: Get regular expression for finding cycles in filenames
//
//  Programmer: Mark C. Miller
//  Creation:   June 13, 2007
//
// ****************************************************************************

std::string
avtDatabaseMetaData::GetCycleFromFilenameRegex()
{
    return cycleFromFilenameRegex;
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::AddDefaultSILRestrictionDescription
//
//  Purpose: Add a string to the description of a suggested default SIL
//           restriction. This string should be "!TurnAllOn", "TurnAllOf",
//           "+<SIL set name>" or "-<SIL set name>".
//
//  Programmer: Gunther H. Weber
//  Creation:   February 04, 2008
//
// ****************************************************************************

void
avtDatabaseMetaData::AddDefaultSILRestrictionDescription(const std::string& setName)
{
    suggestedDefaultSILRestriction.push_back(setName);
    Select(ID_suggestedDefaultSILRestriction, (void *)&suggestedDefaultSILRestriction);
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::Add
//
//  Arguments:
//      smd    A subsets meta data object.
//
//  Programmer: Mark C. Miller
//  Creation:   August 18, 2009
//
// ****************************************************************************

void
avtDatabaseMetaData::Add(avtSubsetsMetaData *smd)
{
    subsets.push_back(smd);
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::GetRestrictedMatnos
//
//  Purpose: Given variable name, return materials it may be restricted to.
//
//  Programmer: Mark C. Miller
//  Creation:   August 26, 2010
//
// ****************************************************************************
#define CHECK_VAR_TYPE(VT)                                  \
    int num ## VT = GetNum ## VT();                         \
    for (i = 0 ; i < num ## VT; i++)                        \
        if (VariableNamesEqual(Get ## VT(i).name, varname)) \
            return Get ## VT(i).matRestricted

const intVector& avtDatabaseMetaData::GetRestrictedMatnos(const std::string& varname) const
{
    int i;
    static intVector dummy;
    CHECK_VAR_TYPE(Scalars);
    CHECK_VAR_TYPE(Vectors);
    CHECK_VAR_TYPE(Tensors);
    CHECK_VAR_TYPE(Arrays);
    CHECK_VAR_TYPE(Labels);
    return dummy;
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::Empty
//
//  Purpose: Return whether md object is empty (devoid of any objects)
//
//  Programmer: Mark C. Miller
//  Creation:   28Oct10
//
// ****************************************************************************
bool avtDatabaseMetaData::Empty() const
{
    return (GetNumMeshes() == 0 && GetNumCurves() == 0);
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::GetGhostZoneTypesPresent
//
//  Purpose:
//      Gets the type of ghost zones present in a particular mesh.
//
//  Arguments:
//      name     The name of a mesh.
//
//  Programmer:  Cyrus Harrison
//  Creation:    Tue Feb  7 11:15:20 PST 2012
//
// ****************************************************************************

int
avtDatabaseMetaData::GetGhostZoneTypesPresent(std::string name) const
{
    for (int i = 0 ; i < GetNumMeshes() ; i++)
    {
        if (GetMeshes(i).name == name)
        {
            return GetMeshes(i).presentGhostZoneTypes;
        }
    }
    return AVT_NO_GHOST_ZONES;
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::GetGhostZoneTypesPresent
//
//  Purpose:
//      Sets type of ghost zones present to AVT_NO_GHOST_ZONES.
//
//  Arguments:
//      name     The name of a mesh.
//
//  Programmer:  Cyrus Harrison
//  Creation:    Tue Feb  7 11:15:20 PST 2012
//
// ****************************************************************************

void
avtDatabaseMetaData::ClearGhostTypesPresent(std::string name)
{
    for (int i = 0 ; i < GetNumMeshes() ; i++)
    {
        if (GetMeshes(i).name == name)
        {
            GetMeshes(i).presentGhostZoneTypes = AVT_NO_GHOST_ZONES;
            break;
        }
    }
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::AddGhostZoneTypePresent
//
//  Purpose:
//      Adds to the types of ghost zones present in a particular mesh.
//
//  Arguments:
//      name     The name of a mesh.
//      v        Type of ghost zones present.
//
//  Programmer:  Cyrus Harrison
//  Creation:    Tue Feb  7 11:15:20 PST 2012
//
// ****************************************************************************

void
avtDatabaseMetaData::AddGhostZoneTypePresent(std::string name,
                                            avtGhostsZonesPresent v)
{
    for (int i = 0 ; i < GetNumMeshes() ; i++)
    {
        if (GetMeshes(i).name == name)
        {
            GetMeshes(i).presentGhostZoneTypes |= v;
            break;
        }
    }
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::GetTotalVarCount
//
//  Purpose: Compute the total number of variables this database has
//
//  Programmer: Mark C. Miller, Thu May 25 19:52:38 PDT 2017
//
// ****************************************************************************

int
avtDatabaseMetaData::GetTotalVarCount(void) const
{
    return GetNumMeshes() +
           GetNumSubsets() +
           GetNumScalars() +
           GetNumVectors() +
           GetNumTensors() +
           GetNumSymmTensors() +
           GetNumArrays() +
           GetNumMaterials() +
           GetNumSpecies() +
           GetNumCurves() +
           GetNumLabels() +
           GetNumberOfExpressions();
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::GetSEGEnvVarName
//
//  Purpose: Return name of environment variable used to force speculative
//      expression generation (SEG).
//
//  Programmer: Mark C. Miller, Thu May 25 19:52:38 PDT 2017
//
// ****************************************************************************

char const *
avtDatabaseMetaData::GetSEGEnvVarName() const
{
    return "VISIT_FORCE_SPECULATIVE_EXPRESSION_GENERATION";
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::GetSEGWarningString
//
//  Purpose: Return warning string regarding disablement of SEG.
//
//  Programmer: Mark C. Miller, Thu May 25 19:52:38 PDT 2017
//
// ****************************************************************************

char const *
avtDatabaseMetaData::GetSEGWarningString() const
{
    static char msg[2048];
    snprintf(msg, sizeof(msg),
        "Due to the large number of variables, %d, in this database, VisIt has\n"
        "automatically disabled speculative expression generation of ALL forms\n"
        "(e.g. vector-magnitude, mesh-quality, time-derivative, operator-created)\n"
        "because the large number of expressions bogs down GUI performance.\n"
        "You may override this behavior by exiting VisIt and restarting with the\n"
        "environment variable...\n"
        "    \"%s\"\n"
        "set. Be aware that doing so will likely result in sluggish GUI performance.\n"
        "If you need one or more of the expressions VisIt's speculative expression\n"
        "generation process provides and are unwilling or unable to manually create\n"
        "the expression(s) you need, you have no choice in this version of VisIt\n"
        "except to override this behavior and suffer any GUI performance issues.\n"
        "Unfortunately, if you are running in client-server mode, you will have to\n"
        "take action to set this enviornment variable on both the server and client\n"
        "machines. This will only be necessary in VisIt version 2.12.3. An entirely\n"
        "different mechanism for controlling this behavior will be introduced in 2.13.",
         GetTotalVarCount(), GetSEGEnvVarName());
    return msg;
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::IssueSEGWarningMessage
//
//  Purpose: Use IssueWarning method to issue a warning regarding disablement
//      of SEG.
//
//  Programmer: Mark C. Miller, Thu May 25 19:52:38 PDT 2017
//
// ****************************************************************************

void
avtDatabaseMetaData::IssueSEGWarningMessage() const
{
    IssueWarning(GetSEGWarningString());
}

// ****************************************************************************
//  Method: avtDatabaseMetaData::ShouldDisableSEG
//
//  Purpose: Determine if SEG should be disabled based on TotalVarCount and
//      on whether or not the enviornment variable required to override it
//      has been set.
//
//  Programmer: Mark C. Miller, Thu May 25 19:52:38 PDT 2017
//
// ****************************************************************************
bool
avtDatabaseMetaData::ShouldDisableSEG(bool envOverride) const
{
    return GetTotalVarCount() > 1000 && !envOverride;
}

